[英]What happens when constructor throws on vector.emplace or vector.emplace_back?
[英]why does vector.emplace_back call the move-constructor?
struct Object {
Object() { cout << "constructor\n"; }
Object(const Object &) { cout << "copy constructor\n"; }
Object(Object &&) { cout << "move constructor\n"; }
};
int main() {
vector<Object> v;
v.reserve(10);
v.emplace_back(Object{});
}
这给了我以下输出:
建设者
移动构造函数
为什么? 我认为emplace_back确实会在原处创建Object,因此无需调用任何复制或移动构造函数。
根据描述:
元素是就地构造的,即不执行复制或移动操作。
编辑:啊,好的,看来我从根本上误解了emplace_back()。 您不必将Object作为参数,因为它是为您自动创建的。 您只需将Object-constructor的参数提供给emplace_back()。
因此,如果我有一个像这样的新构造函数:
Object(int) { cout << "int constructor\n"; }
我会这样称呼emplace_back:
v.emplace_back(42);
代替这个:
v.emplace_back(Object(42));
现在有意义,非常感谢!
EDIT2:希望我能接受您的所有答复! :-P
emplace_back
转发它的参数向量元素类的构造函数,称为就地上的下一个可用的位置vector
。
v.emplace_back(Object{});
相当于:
{
Object tmp;
v.emplace_back(std::move(tmp));
}
这就是为什么要得到常规构造函数调用以及移动构造函数调用的原因。 如果要使用emplace_back
附加新对象,只需调用:
v.emplace_back();
仅出于完整性考虑, emplace_back
可能调用move构造函数的另一个原因是: emplace_back
可能导致vector
增长,从而将其初始内容移动到其新的内存位置。 这不是这里的问题,因为调用reserve
保证足够的容量,但这通常是问题的答案。
v.emplace_back(Object{});
将调用一个新的placement new new (place) Object(Object{})
因此移动构造函数。
使用v.emplace_back();
为了避免调用额外的对象构造函数,
这将导致new (place) Object;
emplace_back
调用与您传递的参数匹配的任何构造函数。 在这种情况下,您选择传递与Object&&
move构造函数匹配的Object&&
Object{}
。
当描述说“不执行移动或复制”时,表示除指定的对象构造以外。 如果该构造恰好是移动或复制,那么当然可以执行。
如果希望emplace_back
使用no-args构造函数,则不传递任何参数: v.emplace_back()
。
您链接的版本用于传递构造函数参数。 为了达到预期的效果,可以调用v.emplace_back();
您正在emplace_back
与向量中存储的相同类型的对象调用emplace_back
,因此您请求该对象的副本(与Object O(Object{});
)。 由于提供的是临时文件,因此将调用move构造函数而不是copy构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.