Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 移动std::vector时是否需要保留容量?_C++_C++11_Stdvector_Language Lawyer_Move Semantics - Fatal编程技术网

C++ 移动std::vector时是否需要保留容量?

C++ 移动std::vector时是否需要保留容量?,c++,c++11,stdvector,language-lawyer,move-semantics,C++,C++11,Stdvector,Language Lawyer,Move Semantics,考虑以下代码: std::vector vec; vec.reserve(500); size_t cap = vec.capacity(); std::vector newVec = std::move(vec); assert(cap == newVec.capacity()); 在您遇到的几乎所有实现中,这都是可行的。我不在乎实现做什么。我想知道标准要求什么。移动到向量的容量是否与原始向量相同?或者断言会触发吗?看看标准,似乎移动构造函数不需要任何东西,但是正如@amaurea所说,如

考虑以下代码:

std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();

std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());

在您遇到的几乎所有实现中,这都是可行的。我不在乎实现做什么。我想知道标准要求什么。移动到
向量的
容量是否与原始向量相同?或者断言会触发吗?

看看标准,似乎移动构造函数不需要任何东西,但是正如@amaurea所说,如果移动构造函数尝试分配或释放内存,它将完全违背移动语义的目的,因此,我希望所有实现中的容量保持不变


23.2.1一般集装箱要求

表情

断言/注释前置/后置条件

要求:
T
可复制插入X(见下文)。
post:
u==a



本标准仅要求
newVec==vec
。由于
std::vector::operator=
未考虑容量,因此
newVec
不必具有与
vec
相同的容量
std::vector
的C++11移动构造函数的标准要求是(表99-分配器感知容器要求):

  • 分配器的移动构造不应通过异常退出
  • 立柱:u应具有与施工前rv相同的构件;在此构造之前,
    get\u分配器()
    的值应与
    rv.get\u分配器()
    的值相同
  • 复杂性:常数
这里没有容量要求/保证。但我们可以得出这样的结论:恒定的复杂性隐含地否定了任何再分配。除重新分配外,我看不到任何其他改变容量的逻辑原因。所以应该是一样的

从另一个角度来看,如果moved From向量为空,则忽略它并使用默认构造本身是完全合法的。这仍然是O(1),因为它不需要任何每元素构造。(感谢您对本期的支持)

另外,实现可能会使用
std::allocator::allocate
函数的
hint
参数将容量缩小到原来的大小:

pointer allocate(size_type, allocator<void>::const_pointer hint = 0);
指针分配(大小\类型,分配器::常量\指针提示=0);
未指定
hint
的用法,但如果实现需要,则其目的是帮助实现局部性。因此,某些特定的解决方案可能会将向量存储指针作为
hint
传递,并在其上使用
realloc
来缩减容量


结论:看来标准并不能保证在移动时保持容量
std::vector
,存储空间可能会缩小。

如果容量发生变化,这将彻底打破移动语义的最初动机,即避免不必要的复制和重新分配。不过,我手头没有标准,所以我不能给你一个正确的答案。“但我们可以得出结论,恒定的复杂性隐含着拒绝任何再分配。”+1看起来像实现一样,只会将容量减小到一定的大小,并且仍然满足所有法律要求,虽然这将是一种毫无意义的浪费。@aschepler:但是
std::allocator
接口的哪一部分可以在封面下使用
realloc
?@Rost:这里的问题是,既然
vec
是空的,那么
newVec
忽略从对象移动的空对象和默认构造本身是完全合法的。这仍然是O(1),因为它不需要任何每元素构造。@Peter Alexander噢,我终于看到了。但是,等等!在堆栈上和通过
分配:运算符new(size\u t)
不是相同的可观察行为!你回答的第一段与最后一段中的警告相矛盾,因此很难说你的断言更有力。
X(rv)
X u(rv)
pointer allocate(size_type, allocator<void>::const_pointer hint = 0);