std :: vector,默认构造,C++ 11和重大变化

Ale*_* C. 53 c++ stl vector backwards-compatibility c++11

我今天跑了一个非常微妙的问题我希望得到你的意见.

考虑以下花园式共享体成语类:

struct S
{
    S() : p_impl(new impl) {}
private:
    struct impl;
    boost::shared_ptr<impl> p_impl;
};
Run Code Online (Sandbox Code Playgroud)

当您尝试以下列方式将它们放入向量时,会出现这种乐趣:

std::vector<S> v(42);
Run Code Online (Sandbox Code Playgroud)

现在,至少使用MSVC 8,所有元素v共享同一个impl成员.实际上,导致这种情况的原因是vector构造函数:

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

在这些场景中,只有一个S对象被默认构造,从中复制了它们的n元素vector.

现在,使用C++ 11,有rvalue引用.所以它不能像这样工作.如果a vector被构造为

std::vector<S> v(42);
Run Code Online (Sandbox Code Playgroud)

然后很可能,实现将选择默认构造n向量内的对象,因为复制构造可能不可用.在这种情况下,这将是一个突破性的变化.

我的问题是:

  1. C++ 03标准是否std::vector必须具有如上定义的构造函数,即.使用默认参数?特别是保证向量对象的条目被复制而不是默认构造?
  2. C++ 11标准对同一点有什么看法?
  3. 我认为这可能会导致C++ 03和C + 11之间发生重大变化.这个问题是否已被调查过?解决了 ?

PS:请不要评论S上面类的默认构造函数.这是或实施某种形式的懒惰建筑.

Jam*_*lis 46

C++ 03标准是否std::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)
Run Code Online (Sandbox Code Playgroud)

除了它不再具有第二个参数的默认参数之外,(1)的工作方式与在C++ 03中的工作方式相同: x复制n时间.

代替默认参数x,已添加(2).此构造函数值初始化n容器中的元素.没有制作副本.

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

std::vector<S> v(42, S());
Run Code Online (Sandbox Code Playgroud)

我认为这可能会导致C++ 03和C++ 11之间发生重大变化.我认为这可能会导致C++ 03和C++ 11之间发生重大变化.这个问题是否已被调查过?解决了?

是的,正如你的例子所示,这确实是一个突破性的变化.

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

  • @Alexandre:那不是.还有一些其他情况会破坏向后兼容性.他们只是在可以避免的时候或者当不值得的时候尽量不去做.但绝对100%的向后兼容性多年来一直没有出现在桌面上. (9认同)
  • @Nemo:当然,我正在回应Alexandre C,"要么语言向后兼容,要么不是".它不是,而且是公然的.如果他想要三分法,"要么语言向后兼容;要么它不是;或者C++ 03中的每个格式良好的程序要么在C++ 0x中维护C++ 03所保证的所有行为,要么在C++ 0x中形成错误,然后他可以使用那种三分法而不是二分法.它仍然"不",只是不那么公然,我同意我们不能拥有第三个,这是可惜的. (3认同)