今天我遇到了一个非常微妙的问题,我想征求您的意见.
考虑以下花园式的共享体习语类:
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
对象被默认构造,vector
的n
元素是从它复制过来的.
现在,在 C++11 中,有右值引用.所以它不能像这样工作.如果一个 vector
被构造为
std::vectorv(42);
那么很可能,实现将选择默认构造向量内的 n
对象,因为复制构造可能不可用.在这种情况下,这将是一个重大变化.
我的问题是:
std::vector
必须具有如上定义的构造函数,即.使用默认参数?特别是是否可以保证向量对象的条目被复制而不是默认构造?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:
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 ?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 和重大更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!