gcc 4.7.0中std::vector::resize()的奇怪行为
strange behaviour of std::vector::resize() with gcc 4.7.0
我仍然对std::vector::resize()
的行为感到困惑。考虑以下代码(另请参阅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&&)
}
如果没有A::A(A const&)
或A::A(A&&)
,则带有a.resize(4);
的行不会编译。然而,该构造函数从未被调用:assert(0)
不会激发!有人能向我解释一下吗?
我的解释是,allocator_traits<>
(由std::vector::resize()
使用)的模板魔术需要存在这两个构造函数中的任何一个,但实际上从未调用过。但是,如果不调用方法,为什么要要求它存在?
标准的最新修订版(n3376)说:
12-如果CCD_ 8,将
sz - size()
默认插入的元素追加到序列中
13-要求:T
应为MoveInsertable
,DefaultInsertable
应为*this
。
这意味着MoveInsertable
是可能发生的任何重新分配所必需的,而DefaultInsertable
是实际追加所必需的。因此,只有当向量已经包含元素并且需要重新分配时,复制或移动构造函数才会启动。
事实上,如果我们写:
std::vector<A> a;
a.resize(1);
assert(!a.empty() && a.capacity() < 4);
a.resize(4);
然后调用A
的复制或移动构造函数,并触发断言。
为了resize
矢量,如果矢量没有足够的空间容纳新大小所需的元素,则必须将现有元素放置到新分配的内存块中。这是通过复制构建它们来完成的。所以你必须有一个复制构造函数来调整向量的大小。在这种情况下,不存在现有的元素,因此不会调用复制构造函数。但它仍然必须存在。
在您的示例中,当您调用vector::resize()方法时,将调用构造函数而不是复制构造函数。这就是为什么您看不到断言被触发的原因。
至于为什么你需要复制构造函数(和移动构造函数,你还没有定义和声明),是因为模板类型必须是可复制可构造的和可移动可构造的。【集装箱要求概述】/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);
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中用vector填充一个简单的动态数组
- vector.resize()中的分配错误
- 使用std::vector的OpenCL矩阵乘法
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 在某些循环内使用vector.push_back时出现分段错误
- 当vector是tje全局变量时,c++中vector的内存管理
- std::vector的包装器,使数组的结构看起来像结构的数组
- 奇怪的结构&GCC&clang(void*返回类型)
- GCC本机矩阵运算库
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 为什么 GCC 不能假设 std::vector::size 在这个循环中不会改变?
- gcc 4.7.0中std::vector::resize()的奇怪行为
- 将std::vector作为模板模板参数传递时出错-在GCC中有效,在MSVC中失败
- 如何解决 gcc 4.7 和 4.9 之间 std::vector 的不同行为
- 我无法再将 char[M][N] 类型分配给 gcc 4.9 上的 std::vector
- GCC 和 VC++ 之间的 std::vector::emplace_back 差异
- 为什么在gcc-4.9.1-4ubuntu2中没有手动输入std::vector
- C++-为什么插入类型的顺序会影响Vector性能(GCC 4.81)