Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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++ 为什么要将T型放置在需要可移动构造的向量末端?_C++_C++11_Move_Stdvector_Move Semantics - Fatal编程技术网

C++ 为什么要将T型放置在需要可移动构造的向量末端?

C++ 为什么要将T型放置在需要可移动构造的向量末端?,c++,c++11,move,stdvector,move-semantics,C++,C++11,Move,Stdvector,Move Semantics,为什么公共构造函数(和析构函数)不足以将t类型的对象放置在向量的后面?以下代码段格式不正确 #include <vector> struct Foo { Foo() {} Foo(int) {} ~Foo() {} Foo(const Foo&) = delete; Foo& operator=(const Foo&) = delete; }; int main() { std::vector<Foo> vfoo(10

为什么公共构造函数(和析构函数)不足以将
t
类型的对象放置在向量的后面?以下代码段格式不正确

#include <vector>

struct Foo {
  Foo() {}
  Foo(int) {}
  ~Foo() {}

  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;
};

int main() {
  std::vector<Foo> vfoo(10);

  vfoo.emplace_back();
}
#包括
结构Foo{
Foo(){}
Foo(int){}
~Foo(){}
Foo(const Foo&)=删除;
Foo&运算符=(const Foo&)=删除;
};
int main(){
std::向量vfoo(10);
vfoo.emplace_back();
}

emplace\u back
要求
Foo
至少是可移动构造的,并且此代码无法编译,因为移动构造函数与复制构造函数一起被删除。但是我想象
emplace\u back
使用placement new调用默认构造函数。

在您的示例中,向量是用
10
元素构造的

然后添加一个。如果
capacity()
中没有更多的空间,则必须分配一个新的缓冲区,必须将已有的10个元素移到其中,然后添加新元素

您会注意到上面的单词
move
——这就是您需要move的原因

此外,即使您没有元素,或者您仔细确保有足够的容量,编译器也无法知道:移动现有元素的代码将被编译(如果不运行),您将得到错误

vector
中缺少“向后推,我保证已经有容量”方法。再加上“设置容量,放弃任何现有元素”,可以让您添加元素而不需要移动或复制ctor回退。在
emplace
发明之前,所有添加元素都需要一个副本或移动:在C++11之前,所有添加元素都需要一个副本。这两种方法缺乏奇怪的语义,只是为了允许不可移动类型限制使用
向量
,这并不奇怪


我鼓励您编写一个包含这两个扩展(或类似的扩展)的容器,并建议将其添加到C++中:这可能对高性能用例也有帮助(编译器能够证明我确实确保了在我的经验中足够的容量).

当调整容器大小并且需要复制现有内容时,您预计会发生什么?请参阅@o11c
emplace
emplace\u back
上“参数”下的“类型要求”是不同的事情,无论如何,问题是为什么会有这样的要求,不是需求是什么,因为它是这样定义的。“这么简单!”大卫汉姆说。对问题是这样做的理由。如果对象不可移动,但需要重新分配,是否可以删除可移动的要求,并使
emplace\u back
抛出?(如果我们不想更改新的emplace函数,也可以使用另一个名称的新emplace函数)@mattmcnab肯定需要单独的函数。就我所知,不可能准确地检测到某个东西是否是可插入的。@T.C.但你可以准确地检测到它(但移动实际上移动的事实无法确定,但这似乎不合理),或者还有其他原因吗?(我猜分配器会很晚失败?@Yakk如何在普通代码中检测到它(没有内部代码)?当然,您可以检测到在直接上下文中,
分配器_traits::construct(m,p,rv)
是否格式良好,但这并不意味着什么,因为实际上要中断的是调用内部的移动。然后,有些东西的移动将在重载解析中失败(move-ctor-deleted或nonexistent),有些东西的移动构造函数将假装存在,然后无法实例化,您只能检测到前者。