[英]strange behaviour of std::vector::resize() with gcc 4.7.0
I'm still confused about the behaviour of std::vector::resize()
. 我仍然对
std::vector::resize()
的行为感到困惑。 Consider the following code (see also type requirements for std::vector<type> ) 考虑以下代码(另请参见std :: vector <type>的类型要求 )
struct A {
A() : X(0) { std::cerr<<" A::A(); this="<<this<<'\n'; }
A(A const&) { assert(0); } // is required but doesn't fire in vector::resize
int X;
};
int main()
{
std::vector<A> a;
a.resize(4); // would not compile without A::A(A const&) or A::A(A&&)
}
Without A::A(A const&)
or A::A(A&&)
, the line with a.resize(4);
如果没有
A::A(A const&)
或A::A(A&&)
,则带有a.resize(4);
doesn't compile. 不编译。 However, that constructor is never called: the
assert(0)
doesn't fire! 但是,永远不会调用该构造函数:
assert(0)
不会触发! Can somebody explain that to me? 有人可以向我解释一下吗?
My interpretation is that the presence of either of these constructors is required by the template magic of allocator_traits<>
(used by std::vector::resize()
), but is actually never called. 我的解释是,这两个构造函数的存在是
allocator_traits<>
的模板魔术所必需的(由std::vector::resize()
),但实际上从未调用过。 However, why would you require the presence of a method if you're not calling it? 但是,如果不调用方法,为什么要要求存在该方法?
The latest revision of the standard ( n3376 ) says: 该标准的最新版本( n3376 )说:
12 - If
size() < sz
, appendssz - size()
default-inserted elements to the sequence.12-如果
size() < sz
,则将sz - size()
默认插入的元素追加到序列中。
13 - Requires:T
shall beMoveInsertable
andDefaultInsertable
into*this
.13-要求:
T
必须是MoveInsertable
和DefaultInsertable
到*this
。
The implication is that MoveInsertable
is required for any reallocation that might occur, while DefaultInsertable
is required for the actual appending. 这意味着可能发生的任何重新分配都需要
MoveInsertable
,而实际附加则需要DefaultInsertable
。 So your copy or move constructor will fire only if your vector already contains elements and needs to be reallocated. 因此,仅当向量已经包含元素并且需要重新分配时,您的copy或move构造函数才会触发。
Indeed, if we write: 确实,如果我们写:
std::vector<A> a;
a.resize(1);
assert(!a.empty() && a.capacity() < 4);
a.resize(4);
then the copy- or move-constructor of A
is called, and your assert is triggered. 然后调用
A
的复制或移动构造函数,并触发您的断言。
In order to resize
a vector, existing elements must be placed into the newly-allocated chunk of memory if the vector didn't have enough space to hold the elements required by the new size. 为了
resize
向量的resize
,如果向量没有足够的空间来容纳新大小所需的元素,则必须将现有元素放入新分配的内存块中。 This is done by copy-constructing them. 这是通过复制构造它们来完成的。 So you must have a copy constructor to resize a vector.
因此,您必须具有复制构造函数才能调整向量的大小。 In this case, there are no existing elements, so the copy constructor is not called.
在这种情况下,不存在现有元素,因此不会调用复制构造函数。 But it still must be present.
但是它仍然必须存在。
In your example, when you call vector::resize() method, the constructor is called instead of the copy constructor. 在您的示例中,当您调用vector :: resize()方法时,将调用构造函数,而不是复制构造函数。 That is why you do not see assert being triggered.
这就是为什么您看不到断言被触发的原因。
As for why you need the copy-constructor (and move constructor, which you haven't defined and declared), is that the template types have to be Copy-constructable and move-constructable. 至于为什么需要copy-constructor(以及尚未定义和声明的move构造函数)的原因是,模板类型必须是Copy-constructable和move-constructable的。 [container.requirements.general]/15 defines the requirements for container's type :
[container.requirements.general] / 15定义了容器类型的要求:
— T is DefaultInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p);
— An element of X is default-inserted if it is initialized by evaluation of the expression allocator_traits<A>::construct(m, p);
where p is the address of the uninitialized storage for the element allocated within X.
— T is CopyInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, v);
— T is MoveInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, rv);
— T is EmplaceConstructible into X from args , for zero or more arguments args, means that the following expression is well-formed: allocator_traits<A>::construct(m, p, args);
— T is Erasable from X means that the following expression is well-formed: allocator_traits<A>::destroy(m, p);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.