简体   繁体   English

为什么vector.emplace_back调用move-constructor?

[英]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{});
}

This gives me the following output: 这给了我以下输出:

constructor 建设者
move constructor 移动构造函数

Why? 为什么? I thought that emplace_back does create the Object in place, so that no copy or move constructors have to be called. 我认为emplace_back确实会在原处创建Object,因此无需调用任何复制或移动构造函数。
From the description: 根据描述:

The element is constructed in-place, ie no copy or move operations are performed. 元素是就地构造的,即不执行复制或移动操作。

EDIT: Ah, okay, it seems that I fundamentally misunderstood emplace_back(). 编辑:啊,好的,看来我从根本上误解了emplace_back()。 You don't have to have the Object as an argument, since it is automatically created in place for you. 您不必将Object作为参数,因为它是为您自动创建的。 You only have to give the arguments for the Object-constructor to emplace_back(). 您只需将Object-constructor的参数提供给emplace_back()。

So, if I had a new constructor like this: 因此,如果我有一个像这样的新构造函数:

Object(int) { cout << "int constructor\n"; }   

I would call emplace_back like this: 我会这样称呼emplace_back:

v.emplace_back(42);  

instead of this: 代替这个:

v.emplace_back(Object(42));

Makes sense now, thanks a lot! 现在有意义,非常感谢!

EDIT2: I wish I could accept all of your answers! EDIT2:希望我能接受您的所有答复! :-P :-P

emplace_back forwards its arguments to the constructor of the vector element class, called in-place on the next available position of the vector . emplace_back转发它的参数向量元素类的构造函数,称为就地上的下一个可用的位置vector

v.emplace_back(Object{});

is sort of equivalent to: 相当于:

{
     Object tmp;
     v.emplace_back(std::move(tmp));
}

That's why you are getting a regular constructor call followed by a move constructor call. 这就是为什么要得到常规构造函数调用以及移动构造函数调用的原因。 If you want to append a new object with emplace_back , just call: 如果要使用emplace_back附加新对象,只需调用:

v.emplace_back();

Just for the sake of completeness, another reason why emplace_back might call a move constructor is: emplace_back may cause the vector to grow, and thus move its initial contents to their new memory location. 仅出于完整性考虑, emplace_back可能调用move构造函数的另一个原因是: emplace_back可能导致vector增长,从而将其初始内容移动到其新的内存位置。 This is not the problem here, because calling reserve guarantees enough capacity, but generally it's an answer to the question. 这不是这里的问题,因为调用reserve保证足够的容量,但这通常是问题的答案。

v.emplace_back(Object{}); will call a placement new new (place) Object(Object{}) so a move constructor. 将调用一个新的placement new new (place) Object(Object{})因此移动构造函数。

Use v.emplace_back(); 使用v.emplace_back(); to avoid to call extra object constructor, 为了避免调用额外的对象构造函数,
which will result in new (place) Object; 这将导致new (place) Object;

emplace_back calls whatever constructor matches the arguments you pass it. emplace_back调用与您传递的参数匹配的任何构造函数。 In this case you have chosen to pass Object{} , which matches the Object&& move constructor. 在这种情况下,您选择传递与Object&& move构造函数匹配的Object&& Object{}

When the description says, "no move or copy is performed", it means apart from the object construction that you specify. 当描述说“不执行移动或复制”时,表示除指定的对象构造以外。 If that construction happens to be a move or copy then of course it is performed. 如果该构造恰好是移动或复制,那么当然可以执行。

If you want emplace_back to use the no-args constructor then pass it no arguments: v.emplace_back() . 如果希望emplace_back使用no-args构造函数,则不传递任何参数: v.emplace_back()

The version you are linking is for passing constructor arguments. 您链接的版本用于传递构造函数参数。 To achieve the desired effect, you could call v.emplace_back(); 为了达到预期的效果,可以调用v.emplace_back();

You are calling emplace_back with an object of the same type that is stored in the vector so you are requesting a copy of that object (Same as Object O(Object{}); ). 您正在emplace_back与向量中存储的相同类型的对象调用emplace_back ,因此您请求该对象的副本(与Object O(Object{}); )。 Since you provide a temporary, the move constructor is invoked instead of the copy constructor. 由于提供的是临时文件,因此将调用move构造函数而不是copy构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当构造函数抛出vector.emplace或vector.emplace_back时会发生什么? - What happens when constructor throws on vector.emplace or vector.emplace_back? 为什么vector :: push_back和emplace_back调用value_type :: constructor两次? - Why does vector::push_back and emplace_back call value_type::constructor twice? 为什么在调用std :: vector :: emplace_back()时调用复制构造函数? - Why is copy constructor called in call to std::vector::emplace_back()? 为什么emplace_back需要移动构造函数 - why does emplace_back need move constructor 为什么不调用move-constructor? - Why is the move-constructor not called? 为什么不调用移动构造函数? - Why is move-constructor not called? vector.emplace_back()和vector.push_back()做同样的事情吗? - Do vector.emplace_back() and vector.push_back() do the same thing? 使用emplace_back避免移动构造函数调用的最佳方法是什么? - Best way to use emplace_back to avoid move constructor call? 安全使用vector.emplace_back(new MyPointer); 向量内部故障会导致内存泄漏吗? - Safe to use vector.emplace_back( new MyPointer ); Could failure inside vector lead to leaked memory? 为什么矢量 <T> :: \\ templace_back,这样T有一个删除的拷贝构造函数,无法编译? - Why does vector<T>::emplace_back, such that T has a deleted copy constructor, fail to compile?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM