Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.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++ 为什么emplace_back需要移动构造函数_C++_C++11 - Fatal编程技术网

C++ 为什么emplace_back需要移动构造函数

C++ 为什么emplace_back需要移动构造函数,c++,c++11,C++,C++11,我有以下代码: #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 pr

我有以下代码:

#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");
}
但是,如果删除了移动构造函数:

[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
[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:在“void std::_construct(_T1*,_Args&&&…[带_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:static_ForwardIterator std::_uninitialized_copy:_uninit_copy(_inputierator,_inputierator,_ForwardIterator,_ForwardIterator)[带(inputierator=std::move)移动(迭代器;(转发器=Test*;bool)bool)值类型=false]中需要
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../../../include/c++/4.7.2/bits/stl_uninitialized.h:119:41:从“_forwarditeratorstd::uninitialized_copy(_inputierator,_inputierator,_ForwardIterator,_ForwardIterator)[with_inputierator=std::move_iterator;_ForwardIterator=Test*]中需要”
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../include/c++/4.7.2/bits/stl_uninitialized.h:260:63:从“_forwarditeratorstd::_uninitialized_copy_a(_inputierator,_inputierator,_ForwardIterator,std::allocator&])[带_inputierator=std::move_迭代器;_ForwardIterator=Test*)
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../../include/c++/4.7.2/bits/stl_未初始化。h:283:69:从“_forwarditeratorstd::_uninitialized_move_if_noexcept_a(_InputIterator,_InputIterator,_ForwardIterator,_ForwardIterator,_分配器,)分配器&)[带_InputIterator=Test*)(转发器=Test*)分配器],)分配器]中必须输入
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../../include/c++/4.7.2/bits/vector.tcc:410:6:void std::vector::_M_emplace_back_aux(_Args&&…[with _Args={const char(&)[13]};_tptest;_Alloc=std::allocator
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../../../include/c++/4.7.2/bits/vector.tcc:102:4:从“void std::vector::emplace_back(_Args&&&…)[with _Args={const char(&)[13]};_tptest;_Alloc=std::Alloc::alloctor]中需要
main.cpp:32:32:此处为必填项
main.cpp:14:3:错误:“Test::Test(Test&&)”是私有的
在/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../include/c++/4.7.2/vector:63:0中包含的文件中,
来自main.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../../include/c++/4.7.2/bits/stl_construct.h:77:7:错误:在此上下文中
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../../../../../include/c++/4.7.2/bits/stl_construct.h:77:7:错误:使用删除的函数“Test::Test(Test&)”
main.cpp:14:3:错误:在此处声明

但是
emplace\u back
不使用移动构造函数。为什么初始化在此实例中需要移动构造函数?

如问题后的注释所述。
emplace\u back
操作员可能需要重新分配容器内存,因此
vector
模板类型需要是可复制或可移动的


问题不在于参数的转发,而在于为新对象分配内存。

如果向量中没有空间,那么它应该分配新空间并将所有内容移动到那里,为了避免对象包含或拥有的资源的副本(向量内),需要移动

对于
测试类型的向量

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

如果在
gcc 4.7.2
错误的情况下执行此操作,则炮位本身不需要这两种情况。但是,对于重增长,
T
至少需要是可移动的
MoveConstructible
,这也是
std::vector
@Xeo的一般要求,有什么不对?重新定位会导致向量重新生长,这需要复制/移动构造函数。因此,重新生长需要复制/移动构造函数。伙计们,请添加这些注释作为答案。当我给出我的答案时,我不想复制这些注释:(还要记住关于移动构造函数的
noexcept
,因为不原子地移动多个元素是不安全的。仅供参考,这在C++11标准的表101中被称为“对于向量,t也应该可以移动插入X”。
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