C++ 中向量的内部工作原理?
我正在做 C++ 练习,但得到了意想不到的输出,我希望有人能解释一下。该练习要求我创建一个名为 rock 的类,它有一个默认构造函数、一个复制构造函数和一个析构函数,所有这些都向 cout 声明自己。
在主要方法中,我尝试按值将此类的成员添加到向量中:
vector<Rock> byValue;
Rock r1, r2, r3;
byValue.push_back(r1);
byValue.push_back(r2);
byValue.push_back(r3);
cout << "byValue populated\n\n";
我期望的输出(并在练习解决方案中显示)是:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
但是我得到的输出是:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
~Rock()
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
任何人都可以解释为什么似乎有额外的调用复制构造函数和析构函数?
Im working on an exercise in C++ but im getting unexpected output I hope someone can explain. The exercise asked that I make a class called rock which has a default constructor, a copy constructor and a destructor all of which announce themselves to cout.
In the main method I am to try and add members of this class to a vector by value:
vector<Rock> byValue;
Rock r1, r2, r3;
byValue.push_back(r1);
byValue.push_back(r2);
byValue.push_back(r3);
cout << "byValue populated\n\n";
The output I expected (and shown in the exercise solutions) is:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
However the output I get is:
Rock()
Rock()
Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
Rock(const Rock&)
Rock(const Rock&)
Rock(const Rock&)
~Rock()
~Rock()
byValue populated
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
~Rock()
Can anyone explain why there seems to be extra calls to the copy constructor and destructor?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当向量调整大小时,元素必须移动到新位置。
这是正常的。
如果您
在调用
push_back
之前调用,则额外的副本应该会消失。When the vector gets resized, the elements have to be moved to their new location.
This is normal.
If you call
before any calls to
push_back
, the extra copies should disappear.向量连续存储其元素。为了避免每次插入元素时总是重新分配内存,它确实分配了一堆内存。这就是为什么向量有两种关于其“大小”的方法:
size()
表示存储的元素数量,capacity()
表示分配的内存量。通常(但这取决于 STL 实现),它的增长方式是其先前容量的两倍。当它分配更多内存时,并且由于数据必须连续存储(与
list
相比),它必须移动其内部数据; STL 会复制数据,这就是为什么要多次调用构造函数/析构函数。如果您知道向量中将存储多少个元素,则可以使用
reserve
来指示首先应分配多少内存。A vector stores its elements contiguously. In order to avoid always re-allocating memory each time an element is inserted, it does allocate a bunch of memory. That is why vector has two methods regarding its "size":
size()
which tells the number of elements stored, andcapacity()
which indicates the amount of memory allocated.Usually (but that is dependent on the STL implementation), it grows by doubling its precedent capacity. When it allocates more memory, and because data has to be stored contiguously (compared to a
list
), it has to move its internal data; and the STL copies data, which is why you have so many calls to the constructor/destructor.If you know how many elements will be stored in your vector, you can use
reserve
to indicate how much memory it should allocated at first.std::vector
用于存储元素的内存量有限。您可以通过capacity
查询到底有多少。您还可以使用reserve
方法告诉向量获取额外的内存。当您将一个元素推入向量且其容量为零(它已用完所有额外内存)时,它会分配一个新的更大数组并从原始数组中复制元素。这就是所有额外副本的来源。
看看你的输出,看起来向量必须增长两倍。如果您将代码更改为在推送任何内容之前调用保留,则向量将永远不需要增长,并且不会有额外的副本。
下面是一个详细的代码片段,展示了所有这些如何结合在一起:ideone.com
std::vector
has a limited amount of memory to store elements. You can query just how much withcapacity
. You can also tell the vector to grab extra memory, with thereserve
method.When you push an element onto the vector and its capacity is zero (it has used up all of it extra memory) it allocates a new larger array and copies the elements from the original. That is where all the extra copies are coming from.
Looking at your output it looks like the vector had to grow twice. If you changed to code to call reserve before pushing anything the vector would never need to grow and there would be no extra copies.
Here is a verbose code snippet that shows how all of this comes together: ideone.com