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

今天我遇到了一个非常微妙的问题,我想征求您的意见.

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

struct S{S() : p_impl(new impl) {}私人的:结构体;boost::shared_ptr<impl>p_impl;};

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

std::vectorv(42);

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

template 类向量{向量(size_t n, const T& x = T(), const A& a = A());...};

在场景下,只有一个S对象被默认构造,vectorn元素是从它复制过来的.

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

std::vectorv(42);

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

我的问题是:

  1. C++03 标准是否要求 std::vector 必须具有如上定义的构造函数,即.使用默认参数?特别是是否可以保证向量对象的条目被复制而不是默认构造?
  2. C++11 标准对同一点有何看法?
  3. 我认为这是在 C++03 和 C+11 之间进行重大更改的可能性.这个问题有调查过吗?解决了吗?

PS:请不要对上述 S 类的默认构造函数发表评论.就是这样或者实现了某种形式的惰性构造.

解决方案

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

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

<小时><块引用>

C++11 标准对同一点有何看法?

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

vector(size_type n, const T& x, const Allocator& = Allocator());//(1)显式向量(size_type n);//(2)

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

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

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

std::vectorv(42, S());

<小时><块引用>

我认为这是在 C++03 和 C++11 之间进行重大更改的可能性.我认为这是在 C++03 和 C++11 之间进行重大更改的可能性.有没有调查过这个问题?解决了?

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

由于我不是 C++ 标准化委员会的成员(并且我没有特别密切关注邮件中与库相关的论文),我不知道讨论了这个重大变化的程度.

>

I ran today against a quite subtle issue I'd like to have your opinion on.

Consider the following garden-variety shared-body-idiom class:

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

The fun appears when you try to put those into vectors in the following way:

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

Now, with MSVC 8 at least, all the elements in v share the same impl member. Actually, what causes this is the vector constructor:

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

Under the scenes, only one S object gets default constructed, the n elements of the vector are copied from it.

Now, with C++11, there are rvalue references. So it cannot work like this. If a vector is constructed as

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

then most likely, implementations will chose to default construct the n objects inside the vector, since copy construction may not be available. This would be a breaking change in this case.

My question is:

  1. Does the C++03 standard mandates that std::vector must have a constructor defined as above, ie. with a default argument ? In particular is there a guarantee that the entries of the vector object get copied instead of default constructed ?
  2. What does the C++11 standard say about this same point ?
  3. I see this as a possibility for a breaking change between C++03 and C+11. Has this issue been investigated ? Solved ?

PS: Please no comments about the default constructor of the class S above. It was this or implementing some form of lazy construction.

解决方案

Does the C++03 standard mandate that std::vector must have a constructor defined as above, i.e. with a default argument? In particular is there a guarantee that the entries of the vector object get copied instead of default constructed?

Yes, the specified behavior is that x is copied n times so that the container is initialized to contain with n elements that are all copies of x.


What does the C++11 Standard say about this same point?

In C++11 this constructor has been turned into two constructors.

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

Except for the fact that it no longer has a default argument for the second parameter, (1) works the same way as it does in C++03: x is copied n times.

In lieu of the default argument for x, (2) has been added. This constructor value-initializes n elements in the container. No copies are made.

If you require the old behavior, you can ensure that (1) is called by providing a second argument to the constructor invocation:

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


I see this as a possibility for a breaking change between C++03 and C++11. I see this as a possibility for a breaking change between C++03 and C++11. Has this issue been investigated? Solved?

Yes, as your example demonstrates, this is indeed a breaking change.

As I am not a member of the C++ standardization committee (and I haven't paid particularly close attention to library-related papers in the mailings), I don't know to what degree this breaking change was discussed.

相关文章