std :: vector,默认构造,C ++ 11和打破更改 [英] std::vector, default construction, C++11 and breaking changes

查看:430
本文介绍了std :: vector,默认构造,C ++ 11和打破更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



考虑下面花园种类的共享身体习语课程:

/ p>

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

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

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

现在,至少使用MSVC 8, v 共享同一个 impl 成员。实际上,导致这是向量构造函数的原因:

  template<类型名称T,类型名称A = ...> 
类向量
{
vector(size_t n,const T& x = T(),const A& a = A
...
};

在这种情况下,只有一个 S 得到默认构造,从向量 n 元素被复制。



现在,使用C ++ 11,有一些右值引用。所以它不能这样工作。如果向量被构造为

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

那么实现会选择默认构造 n 向量中的对象,因为复制构造可能不可用。这将是一个突破性的变化。



我的问题是:


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

  2. C ++ 11标准对同一点说什么?

  3. 我认为这是C ++ 03和C + 11之间发生突变的可能性。是否已调查此问题?解决了吗?

PS:请不要评论类的默认构造函数 S 上面。

解决方案


++ 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)

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



代替 x 的默认参数,(2)已添加。此构造函数值 - 初始化容器中的 n 元素。



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

  std :: vector< S> v(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.

这篇关于std :: vector,默认构造,C ++ 11和打破更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆