【问题标题】:Internal working of a vector in C++?C ++中向量的内部工作?
【发布时间】:2011-11-23 17:35:18
【问题描述】:

我正在使用 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()

谁能解释为什么似乎对复制构造函数和析构函数有额外的调用?

【问题讨论】:

    标签: c++ vector copy-constructor


    【解决方案1】:

    当向量被调整大小时,元素必须被移动到它们的新位置。

    这是正常的。

    如果你打电话

    byValue.reserve(10);
    

    在调用push_back 之前,多余的副本应该会消失。

    【讨论】:

      【解决方案2】:

      向量连续存储其元素。为了避免每次插入元素时总是重新分配内存,它确实分配了一堆内存。这就是为什么 vector 有两种关于其“大小”的方法:size() 表示存储的元素数量,capacity() 表示分配的内存量。

      通常(但这取决于 STL 实现),它通过将其先例容量增加一倍来增长。当它分配更多内存时,并且由于数据必须连续存储(与list 相比),它必须移动其内部数据;并且 STL 复制数据,这就是为什么你有这么多对构造函数/析构函数的调用。

      如果您知道向量中将存储多少元素,您可以使用reserve 来指示它首先应该分配多少内存。

      【讨论】:

        【解决方案3】:

        std::vector 用于存储元素的内存量有限。您可以使用capacity 查询多少钱。您还可以使用 reserve 方法告诉向量获取额外的内存。

        当你将一个元素压入向量并且它的容量为零(它已经用完所有额外的内存)时,它会分配一个新的更大的数组并从原始数组中复制元素。这就是所有额外副本的来源。

        查看您的输出,看起来向量必须增长两次。如果您在推送任何内容之前更改为调用 reserve 的代码,则向量将永远不需要增长,也不会有额外的副本。

        这是一个详细的代码 sn-p,它显示了所有这些是如何结合在一起的:ideone.com

        【讨论】:

          猜你喜欢
          • 2020-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-16
          • 1970-01-01
          • 1970-01-01
          • 2013-10-22
          • 1970-01-01
          相关资源
          最近更新 更多