vector的扩容机制实现
在做C++ primer的课后题时,有一道为自己写的类定义拷贝控制操作,之后定义一个vector
h.h
#ifndef STRVEC_H_
#define STRVEC_H_
#include <iostream>
#include <stdio.h>
#include <string>
#include <memory>
#include <algorithm>
#include <initializer_list>
#include <memory>
#include <vector>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <set>
#include <map>
using std::cout;
using std::endl;
class String
{
public:
String() :first_c(nullptr), last_c(nullptr) {};
String(const char* chr);
String(const String& s);
String(String&& s) noexcept;//移动构造函数
String& operator=(const String& s);
String& operator=(String&& s) noexcept;
char* begin() const { return first_c; }
char* end() const { return last_c; }
char* c_str() { return first_c; }
~String();
private:
std::allocator<char> alloc;
std::pair<char*, char*>alloc_n_copy(const String& s);
void free();
char* first_c;
char* last_c;
};
String::String(const char* chr)
{
auto len = strlen(chr) + 1;
auto beg = alloc.allocate(len);
first_c = beg;
last_c = beg + len;
memcpy(first_c, chr, len);
printf("默认构造函数\n");
}
String::String(const String& s)
{
auto p = alloc_n_copy(s);
first_c = p.first;
last_c = p.second;
std::cout << "拷贝构造函数" << std::endl;
}
String::String(String&& s) noexcept :
alloc(std::move(s.alloc)), first_c(std::move(s.first_c)), last_c(std::move(s.last_c))
{
printf("%s 移动构造函数\n", first_c);
s.first_c = nullptr; s.last_c = nullptr;
}
String::~String()
{
free();
}
std::pair<char*, char*> String::alloc_n_copy(const String& s)
{
auto data = alloc.allocate(s.last_c - s.first_c);
return { data, std::uninitialized_copy(s.first_c, s.last_c, data) };
}
String& String::operator=(const String& s)
{
auto tmp = alloc_n_copy(s);
free();
first_c = tmp.first;
last_c = tmp.second;
printf("拷贝赋值运算符\n");
return *this;
}
String& String::operator=(String&& s) noexcept
{
if (this != &s)
{
free();
alloc = std::move(s.alloc);
first_c = std::move(s.first_c);
last_c = std::move(s.last_c);
s.first_c = nullptr; s.last_c = nullptr;
printf("移动赋值运算符");
}
return *this;
}
void String::free()
{
if (first_c)
{
std::for_each(first_c, last_c, [this](char& cp) { alloc.destroy(&cp); });
alloc.deallocate(first_c, last_c - first_c);
}
}
#endif
c.cpp
#include"h.h"
int main()
{
std::vector<String> vec;
String a = "aaaa";
printf("%d\n", vec.capacity());
vec.push_back(a);
printf("%d\n", vec.capacity());
vec.push_back("bbbb");
printf("%d\n", vec.capacity());
vec.push_back("bbbb");
printf("%d\n", vec.capacity());
return 0;
}
发现vs 2019,当判断需要扩容的时候,会先将新写入的元素直接放在新的内存位置,然后在把旧元素移动构造 从头到尾移动到新的位置
但是并不知道为什么需要这样的实现,为什么不能直接从头开始移动构造转移
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本