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
对象被默认构造, vector
的n
元素被复制。
现在,用C ++ 11,有右值引用。 所以它不能这样工作。 如果一个vector
被构造成
std::vector<S> v(42);
那么很可能,实现将select默认构造向量中的n
对象,因为复制构造可能不可用。 在这种情况下,这将是一个突破性的变化。
我的问题是:
- C ++ 03标准要求
std::vector
必须有一个如上定义的构造函数,即。 有一个默认的参数? 特别是有保证的vector对象的条目被复制,而不是默认构造? - C ++ 11标准对这一点有什么看法?
- 我认为这是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)不是最优的,现在你必须还清。