【问题标题】:std::vector and Constructorsstd::vector 和构造函数
【发布时间】:2011-06-02 23:45:22
【问题描述】:

std::vector 在为其包含的对象创建新实例时调用哪个构造函数?我的印象是它调用了一个默认构造函数,但是如果没有定义或者编译器正在为我做那件事怎么办?

特别是在这种情况下:

class Foo
{
    public:
        Foo(int size)
        {
            data = new double[size];
        }


        ~Foo()
        {
            delete[] data;
        }

    private:
        double* data;
};

std::vector<Foo> myVector;
Foo bar(5);
myVector.push_back(bar);
//stuff

当对象在构造之前的大小未知时,它如何知道要分配多少内存?

【问题讨论】:

标签: c++ object vector constructor


【解决方案1】:

至少,要编译std::vector&lt;T&gt;T 必须是可复制构造和可复制分配的。如果你想使用std::vector&lt;T&gt;::vector(int)(或std::vector&lt;T&gt;::resize()),那么T必须是默认可构造的。如果不满足这些要求中的任何一个,则代码将无法编译。

...

C++03 标准,第 23.1 节(一般讨论容器):

这些组件中存储的对象类型必须满足CopyConstructible类型(20.1.3)的要求,以及Assignable类型的附加要求。

第 20.1.4 节:

20.1.4 默认构造

不需要默认构造函数。某些容器类成员函数签名将默认构造函数指定为默认参数。如果使用默认参数 (8.3.6) 调用其中一个签名,T() 应该是一个定义明确的表达式 (8.5)。

【讨论】:

  • 不完全正确...只要您不尝试在没有默认初始化程序的情况下调整容器大小,它们就不需要是默认可构造的。
  • @Nemo:当然,您可以通过避免依赖于它们的特定容器功能来规避许多“要求”!
  • @Oli:我相信标准要求他们以这种方式工作。我需要追踪参考吗? :-)
  • @Nemo:有参考就好了!我想得越多,我就越不喜欢我表达我的答案的方式,所以我想把它改正。
  • @Oli:回复“参考会很好!” 2003 标准的第 23.1.3 节说你错了,CopyConstructible 和 Assignable。后来该标准隐含地自相矛盾,并说您毕竟是对的。 (例如,resize() 使用默认构造函数为参数之一提供默认值。)
【解决方案2】:

修复错误后会发生什么:

std::vector<Foo> myVector;
myVector.reserve(10);
myVector.push_back(bar);

是你有两个Foo 实例指向同一个data 缓冲区。它可能会工作一段时间,但最终两个对象都被销毁,析构函数被调用两次(或更多,取决于 vector 是否需要移动其内容)并且缓冲区被双重释放,导致未定义的行为(通常意味着崩溃)。


为了解决vector 的初始内容,它会复制构造您作为参数传入的模式(此参数默认为默认构造的对象,但并非必须如此):

std::vector<Foo> myVector(10, bar); // 10 copies of bar

【讨论】:

  • @Oli:我正在解决“它如何知道要分配多少空间?”通过指出vector 没有为data 缓冲区分配空间,刚好够指针(这是Foo 的实际成员)。但现在我明白你的意思了。
  • 啊!是的,我在 OP 添加第二个问题之前阅读了问题正文。
猜你喜欢
  • 2013-12-08
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
  • 2018-03-12
相关资源
最近更新 更多