gpt4 book ai didi

C++:将自动分配的对象添加到 std::vector

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:05:17 25 4
gpt4 key购买 nike

我写了下面的代码:

#include <iostream>
#include <vector>
using namespace std;

class AClass
{
public:
int data;

AClass()
{ data = -333; cout << "+ Creating default " << data << endl; }

AClass(const AClass &copy)
{ 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 似乎正在复制现有对象,但似乎发生了很多不必要的分配/删除。为什么是这样?另外,为什么第二个版本在我没有提供复制构造函数的情况下仍然有效?

最佳答案

It appears that vector is making copies of existing objects when new ones are added

当你添加一个元素时,例如与 v.push_back(AClass(i)); ,所做的是临时的AClass对象被创建并传递给 push_back . push_back然后必须将此对象复制到容器中。

您看到拷贝的另一个原因是 std::vector将其元素连续存储在数组中。如果底层数组中没有剩余空间并且您尝试将另一个元素添加到末尾,则 std::vector必须创建一个新数组,将旧数组中的元素复制到新数组中,然后在末尾插入新元素。如果您不希望发生这种情况,可以调用 std::vector::reservestd::vector中预留足够的空间在开始插入元素之前,或者您可以使用不同的序列容器,例如 std::deque ,它不会连续存储其元素。

it seems like a lot of unnecessary allocation/deletion is taking place

在 C++ 程序中,对象经常被创建和销毁。请注意,在您的程序中,AClass复制起来很便宜:它的大小可能是四个或八个字节,刚好足以容纳它的 int数据成员。

如果您有一个复制成本很高的类型(例如,您可能有一个包含数千个节点的大型树数据结构),那么是的,复制可能太昂贵了。在这种情况下,您可以将智能指针存储到 std::vector 中动态分配的对象。相反(例如 std::vector<shared_ptr<AClass> > )。如果您的编译器支持右值引用并且具有移动感知标准库实现,则可以通过实现移动构造函数和移动赋值运算符并使用 emplace_back 使复制成本高昂的类型可移动。而不是 push_back .

why does the second version work when I haven't provided a copy constructor?

如果您不声明复制构造函数,编译器会为您提供一个默认的复制构造函数。

关于C++:将自动分配的对象添加到 std::vector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6193889/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com