mil*_*eft 4 c++ stl allocation vector object
我写了以下代码:
#include <iostream>
#include <vector>
using namespace std;
class AClass
{
    public:
        int data;
        AClass() 
        { data = -333; cout << "+ Creating default " << data << endl; }
        AClass(const AClass ©) 
        { data = copy.data; cout << "+ Creating copy of " << data << endl; }
        AClass(int d) 
        { data = d; cout << "+ Creating " << data << endl; }
        ~AClass() 
        { cout << "- Deleting " << data << endl; }
        AClass& operator = (const AClass &a)
        {  data = a.data; cout << "= Calling operator=" << endl; }
};
int main(void)
{
    vector<AClass> v;
    for (int i = 3; i--; )
        v.push_back(AClass(i));
    vector<AClass>::iterator it = v.begin();
    while (it != v.end())
        cout << it->data << endl, it++;
    return 0;
}
该计划的输出是:
+ Creating 2
+ Creating copy of 2
- Deleting 2
+ Creating 1
+ Creating copy of 1
+ Creating copy of 2
- Deleting 2
- Deleting 1
+ Creating 0
+ Creating copy of 0
+ Creating copy of 2
+ Creating copy of 1
- Deleting 2
- Deleting 1
- Deleting 0
2
1
0
- Deleting 2
- Deleting 1
- Deleting 0
然后我将课程改为:
class AClass
{
    public:
        int data;
        AClass(int d) 
        { data = d; cout << "+ Creating " << data << endl; }
        ~AClass() 
        { cout << "- Deleting " << data << endl; }
};
输出变为:
+ Creating 2
- Deleting 2
+ Creating 1
- Deleting 2
- Deleting 1
+ Creating 0
- Deleting 2
- Deleting 1
- Deleting 0
2
1
0
- Deleting 2
- Deleting 1
- Deleting 0
看起来,当添加新对象时,向量正在复制现有对象,但似乎正在进行大量不必要的分配/删除.为什么是这样?另外,为什么第二个版本在我没有提供复制构造函数时有效?
Vector使用T的常规数组作为其存储 - 当您创建其中一个时,它必须以某种方式初始化空间,并且唯一的选项是默认构造函数.稍后,当您设置索引的值时,它会将其复制到该空间.
在第二个版本中,即使您没有提供复制构造函数,也会自动为您生成一个复制构造函数.如果您声明一个私有,然后不实现它,您将看到编译器错误(因为您已禁止生成默认值)
当添加新对象时,向量似乎正在复制现有对象
当您添加元素时,例如v.push_back(AClass(i));,执行的操作AClass是创建并传递给临时对象push_back.  push_back然后必须将此对象复制到容器中.
您看到副本的另一个原因是std::vector将其元素连续存储在数组中.如果底层数组中没有剩余空间并且您尝试向末尾添加另一个元素,则std::vector必须创建一个新数组,将旧数组中的元素复制到新数组中,然后在末尾插入新元素.如果您不希望发生这种情况,可以std::vector::reserve在std::vector开始插入元素之前调用以保留足够的空间,或者可以使用不同的序列容器,例如std::deque,不会连续存储其元素.
似乎发生了许多不必要的分配/删除
在C++程序中,经常创建和销毁对象.请注意,在您的程序中,AClass复制非常便宜:它的大小可能是四个或八个字节,只要大到足以容纳其int数据成员.  
如果你有一个复制昂贵的类型(例如,你可能有一个拥有数千个节点的大型树数据结构),那么复制可能过于昂贵.在这种情况下,您可以将智能指针存储到动态分配的对象std::vector(std::vector<shared_ptr<AClass> >例如,a).如果您的编译器支持rvalue引用并且具有移动感知标准库实现,则可以通过实现移动构造函数并移动赋值运算符并使用emplace_back而不是使用来实现可移动的昂贵类型push_back.
为什么第二个版本在我没有提供复制构造函数时有效?
如果您未声明复制构造函数,则编译器会为您提供默认的复制构造函数.