[英]why does emplace_back need move constructor
I have the following code: 我有以下代码:
#include <string>
#include <vector>
#include <iostream>
class Test final {
public:
Test(const std::string& s)
: s_(s) {
std::cout << "constructing: " << s_ << std::endl;
}
#ifdef NO_MOVE
private:
Test(const Test& t) = delete;
Test(Test&& t) = delete;
#else
public:
Test(const Test& t)
: s_(t.s_) {
std::cout << "copying: " << s_ << std::endl;
};
Test(Test&& t)
: s_(std::move(t.s_)) {
std::cout << "moving: " << s_ << std::endl;
};
#endif
private:
std::string s_;
};
int main() {
std::vector<Test> v;
v.emplace_back("emplace_back");
}
When a move constructor is allowed, the following occurs: 当允许移动构造函数时,会发生以下情况:
[matt test] g++ -std=c++11 main.cpp && ./a.out
constructing: emplace_back
However, if the move constructor is removed: 但是,如果删除了移动构造函数:
[matt test] g++ -std=c++11 main.cpp -DNO_MOVE && ./a.out
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Test; _Args = {Test}]’:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:77:3: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Test*>; _ForwardIterator = Test*; bool _TrivialValueTypes = false]’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:119:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Test*>; _ForwardIterator = Test*]’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:260:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Test*>; _ForwardIterator = Test*; _Tp = Test]’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:283:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Test*; _ForwardIterator = Test*; _Allocator = std::allocator<Test>]’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/vector.tcc:410:6: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {const char (&)[13]}; _Tp = Test; _Alloc = std::allocator<Test>]’
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/vector.tcc:102:4: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {const char (&)[13]}; _Tp = Test; _Alloc = std::allocator<Test>]’
main.cpp:32:32: required from here
main.cpp:14:3: error: ‘Test::Test(Test&&)’ is private
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/vector:63:0,
from main.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: within this context
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function ‘Test::Test(Test&&)’
main.cpp:14:3: error: declared here
But the emplace_back
doesn't use the move constructor. 但是
emplace_back
不使用移动构造函数。 Why does the initialization require a move constructor in this instance? 为什么初始化需要在这个实例中使用移动构造函数?
As specified in the comment after the question. 正如问题后的评论中所指定的那样。 The
emplace_back
operator may need to reallocate the containers memory and as such the vector
template type needs to be either copy or move constructable. emplace_back
运算符可能需要重新分配容器内存,因此vector
模板类型需要是复制或移动可构造的。
It's not the forwarding of the arguments that is the issue it is the allocating of memory for the new object. 这不是转发参数,而是为新对象分配内存的问题。
If there is no space in the vector then it should allocate new space and move everything there and to avoid copy of the resource contained or owned by the objects(inside vector) move is required 如果向量中没有空格,那么它应该分配新空间并将所有内容移动到那里并避免复制对象所包含或拥有的资源(向量内部)移动是必需的
For vector of type Test
对于
Test
类型的矢量
Test object(original)--->resource on heap
Test object(relocated with move constructor)------>resource on heap
Test object(relocated with copy constructor)------>copy of resource on heap
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.