std :: vector,默认构造,C ++ 11和重大更改

今天我跑了一个非常微妙的问题,我想请你的意见。

考虑以下花园式的共同成语成语课:

struct S { S() : p_impl(new impl) {} private: struct impl; boost::shared_ptr<impl> p_impl; }; 

当你试图用下列方法把它们放到vector中时,乐趣就会出现:

 std::vector<S> v(42); 

现在,至less在MSVC 8中, v所有元素共享相同的impl成员。 其实,是什么导致这是vector构造函数:

 template <typename T, typename A = ...> class vector { vector(size_t n, const T& x = T(), const A& a = A()); ... }; 

在场景下,只有一个S对象被默认构造, vectorn元素被复制。

现在,用C ++ 11,有右值引用。 所以它不能这样工作。 如果一个vector被构造成

 std::vector<S> v(42); 

那么很可能,实现将select默认构造向量中的n对象,因为复制构造可能不可用。 在这种情况下,这将是一个突破性的变化。

我的问题是:

  1. C ++ 03标准要求std::vector必须有一个如上定义的构造函数,即。 有一个默认的参数? 特别是有保证的vector对象的条目被复制,而不是默认构造?
  2. C ++ 11标准对这一点有什么看法?
  3. 我认为这是C ++ 03和C + 11之间突破性变化的可能性。 这个问题是否被调查? 解决了 ?

PS:请不要评论上面的类S的默认构造函数。 这是这个或实施某种forms的懒惰build设。

C ++ 03标准要求std::vector必须有一个如上定义的构造函数,即有一个默认参数? 特别是有保证的vector对象的条目被复制,而不是默认构造?

是的,指定的行为是将x复制n次,以便将容器初始化为包含n元素,这些元素都是x所有副本。


C ++ 11标准对这一点有什么看法?

在C ++ 11中,这个构造函数已经变成了两个构造函数。

 vector(size_type n, const T& x, const Allocator& = Allocator()); // (1) explicit vector(size_type n); // (2) 

除了第二个参数不再具有默认参数外, (1)与C ++ 03中的相同: x被复制n次。

代替x的默认参数, (2)已被添加。 这个构造函数的值 – 初始化容器中的n元素。 没有复制。

如果您需要旧的行为,可以通过向构造函数调用提供第二个参数来确保(1)被调用:

 std::vector<S> v(42, S()); 

我认为这是C ++ 03和C ++ 11之间发生重大变化的可能性。 我认为这是C ++ 03和C ++ 11之间发生重大变化的可能性。 这个问题是否被调查? 解决了?

是的,就像你的例子所表明的那样,这确实是一个突破性的改变

由于我不是C ++标准化委员会的成员(我没有特别关注邮件中的图书馆相关文件),我不知道这个突破性变化在什么程度上被讨论过。

我认为你所描述的用例解决scheme并不是最优的,也不是完整的,这就是为什么你升级到C ++ 11时遇到问题。

C ++总是关心语义,当你用c ++编写程序时,你最好理解你的语义。 所以在你的情况下,你希望创buildN个对象,但是当你不改变它们时,你希望它们共享相同的内存来优化。 好主意,但如何做到这一点:1)复制构造函数。 2)静态实现+复制构造函数。 你有考虑过这两个解决scheme

考虑你需要N个对象的M个向量,如果你select第一个场景,共享内存将被分配多less次? 它是M,但是如果我们要创build包含MxN对象的向量,为什么我们需要分配M次内存呢?

所以这里正确的实现是默认指向静态内存,只有当对象改变时才分配内存。 在这种情况下,分配N个对象的M个向量会给你…'共享'内存分配。

在你的情况下,你违反了正确的语义滥用拷贝构造函数,这是:1)不明显2)不是最优的,现在你必须还清。