kni*_*ils 0 c++ constructor c++11
#include <vector>
#include <iostream>
#include <iterator>
using namespace std;
class MoveableClass
{
public:
MoveableClass() {
cout << "Default constructor" << endl;
}
MoveableClass(const MoveableClass& src) {
cout << "Copy constructor" << endl;
}
MoveableClass(MoveableClass&& src) {
cout << "Move constructor" << endl;
}
MoveableClass& operator=(const MoveableClass& rhs) {
cout << "Copy assignment operator" << endl;
return *this;
}
MoveableClass& operator=(MoveableClass&& rhs) {
cout << "Move assignment operator" << endl;
return *this;
}
};
int main()
{
vector<MoveableClass> vecSource(3);
cout << "----" << endl;
MoveableClass mc;
cout << "----" << endl;
vecSource.push_back(mc);
// vecSource.push_back(mc);
// vecSource.push_back(mc);
// vecSource.push_back(mc);
cout << "----" << endl;
// Copy the elements from vecSource to vecOne
vector<MoveableClass> vecOne(vecSource.begin(), vecSource.end());
cout << "----" << endl;
// Move the elements from vecSource to vecTwo
vector<MoveableClass> vecTwo(make_move_iterator(vecSource.begin()),
make_move_iterator(vecSource.end()));
cout << "----" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从上面的代码我有两个疑问:
当我使用2个push_back(mc)函数调用复制ctor时,为什么移动ctor不会从实现类调用3次,即第一次按下1次,第二次推送第一次向量调整大小(后续增长)到不同的内存位置(应该有触发第一次推动的动作)第二次推动第3次
即使我初始化大小为3的向量对象,为什么对于一个push_back(mc),复制ctor的调用增加到4.
输出:
Default constructor
Default constructor
Default constructor
----
Default constructor
----
Copy constructor
Copy constructor
Copy constructor
Copy constructor
----
Copy constructor
Copy constructor
Copy constructor
Copy constructor
----
Move constructor
Move constructor
Move constructor
Move constructor
----
Run Code Online (Sandbox Code Playgroud)
我正在使用的gcc版本是:
> gcc version 4.7.3
Run Code Online (Sandbox Code Playgroud)
UPDATE
谢谢你回复我到了某个地方
为了我的1)我想补充一点
// MoveableClass(const MoveableClass& src) {
// cout << "Copy constructor" << endl;
// }
MoveableClass(MoveableClass&& src) noexcept {
cout << "Move constructor" << endl;
}
....
void fun() {
cout << "hello\n";
}
int main()
{
vector<MoveableClass> vecSource(3);
// vector<MoveableClass>::iterator it;
// vecSource.reserve(3);
cout << "----" << endl;
MoveableClass mc;
cout << "----" << endl;
mc.fun();
vecSource.push_back(mc);
// vecSource.push_back(move(mc));
// vecSource.push_back(move_if_noexcept(mc));
// vecSource.push_back(mc);
// vecSource.push_back(mc);
// vecSource.push_back(mc);
// for(it = vecSource.begin(); it != vecSource.end(); ++it )
// cout << (*it).fun() << endl;
cout << "----" << endl;
// Copy the elements from vecSource to vecOne
vector<MoveableClass> vecOne(vecSource.begin(), vecSource.end());
cout << "----" << endl;
// Move the elements from vecSource to vecTwo
vector<MoveableClass> vecTwo(make_move_iterator(vecSource.begin()),
make_move_iterator(vecSource.end()));
cout << "----" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我编辑了以上代码
// vecSource.push_back(move(mc)); I can call move ctor only
// vecSource.push_back(move_if_noexcept(mc)); I can call move ctor only
understood..
Run Code Online (Sandbox Code Playgroud)
如果我评论复制构造函数我得到编译错误
knils @ knils-HP:IteratorAdapters $ g ++ -g -std = c ++ 0x MoveIterators.cpp
内部编译器错误:重新输入错误报告例程.
如果合适,请提交完整的错误报告,并提供预处理的来源.
请参阅说明.存储在/tmp/ccHhV599.out文件中的预处理源,请将其附加到您的bug报告中.
为什么它给出了这个错误,为什么它不使用它的默认拷贝ctor
2)当我初始化为3时,这是否意味着3个内存位置是用类实例初始化的?
for(it = vecSource.begin(); it != vecSource.end(); ++it )
cout << (*it).fun() << endl;
Run Code Online (Sandbox Code Playgroud)
我无法使用上面的代码它给出了错误
MoveIterators.cpp:48:30: note: mismatched types ‘const _CharT*’ and ‘void’
要添加我认为这里有一个差异,用于调整保留不会调用默认ctor并使内存未初始化的保留.
我认为最好在我们需要的范围内使用保留到某个空间的向量,这样可以避免常规的内存交换.即使它超过它将到新的位置.
UPDATE
对于一段代码更改
vector<MoveableClass> vecSource;
vecSource.push_back(mc);
vecSource.push_back(mc);
Run Code Online (Sandbox Code Playgroud)
我得到的o/p是
复制构造函数复制构造函数移动构造函数
我对此处的订单感到困惑.我期待它复制构造函数移动构造函数复制构造函数
因为第一次推送它初始化一个大小(副本)第二次它重新分配,所以将现有内存移动到新位置(移动)和复制第二次推送新位置(复制)编译器不同为什么..
问候!
向量被调整大小(后续增长)到不同的内存位置(应该首先按下触发移动)
std::vector只有在使用noexcept说明符声明了move-constructor 或者没有可用的copy-constructor时,才会在重新分配期间使用move-constructor (std::move_if_noexcept有关详细信息,请参阅参考资料):
通过添加以下小改动:
MoveableClass(MoveableClass&& src) noexcept {
// ~~~~~~~^
cout << "Move constructor" << endl;
}
Run Code Online (Sandbox Code Playgroud)
你会得到输出:
Copy constructor
Move constructor
Move constructor
Move constructor
Run Code Online (Sandbox Code Playgroud)
该noexcept说明符告诉std::vector它可以安全地应用实现移动语义其内容.否则,您将没有强大的异常安全保证,这基本上表明如果重新分配由于异常而导致向量保持不变:
§23.3.6.5[vector.modifiers]/p1:
要求:如果除了复制构造函数之外引发异常,则移动构造函数,赋值运算符或移动赋值运算符
T或通过任何InputIterator运算都没有效果.如果非移动构造函数抛出异常,CopyInsertable T则不指定效果.
此外,push_back成员函数不会尝试移动构造一个新元素,除非它的参数可以被非const右值引用绑定 - 如果不是,那么它将回退到复制构造.如果要基于调用中的mc实例移动构造新元素push_back,则需要传入xvalue mc:
vecSource.push_back(std::move(mc));
// ~~~~~~~~^
Run Code Online (Sandbox Code Playgroud)
输出:
Move constructor
Run Code Online (Sandbox Code Playgroud)
即使我初始化大小为3的向量对象,为什么对于一个push_back(mc),复制ctor的调用增加到4.
vecSource可以使用.capacity()成员函数查询的初始容量可能3 在您的情况下设置,这意味着任何存储更多元素的尝试都会导致需要重新分配,这需要已经存储在向量中的所有元素被复制构造到新的存储位置.
通过在接下来的push_back呼叫之前保留足够的存储空间,可以避免意外的重新分配:
vector<MoveableClass> vecSource;
vecSource.reserve(4); // reserve a storage for 4 elements
vecSource.resize(3); // default-construct 3 elements
cout << "----" << endl;
MoveableClass mc;
vecSource.push_back(mc); // copy-construct 4th element
Run Code Online (Sandbox Code Playgroud)
输出:
Default constructor
Default constructor
Default constructor
----
Default constructor
Copy constructor
Run Code Online (Sandbox Code Playgroud)
2)当我初始化为3时,这是否意味着3个内存位置是用类实例初始化的?
是的,通过在向量的构造函数调用中给出初始容量,或者通过使用resize成员函数,在C++ 11中,您获得了默认构造的数量(在C++ 03中 - 从默认构造的元素复制构造)准备好访问和使用的元素.
cout << (*it).fun() << endl;我无法使用上面的代码它给出了错误
您无法打印出声明void为返回类型的函数调用的结果.只需删除该cout部分,它将编译:
for(auto it = vecSource.begin(); it != vecSource.end(); ++it )
(*it).fun();
Run Code Online (Sandbox Code Playgroud)
如果我评论复制构造函数我得到编译错误
某些操作要求vector元素的类型为CopyConstructible ; 在你的代码中这些是:
vecSource.push_back(mc);
//...
vector<MoveableClass> vecOne(vecSource.begin(), vecSource.end());
Run Code Online (Sandbox Code Playgroud)
"复制构造函数复制构造函数移动构造函数." 我对此处的订单感到困惑.我期待它"复制构造函数移动构造函数复制构造函数"
对于以下代码:
vector<MoveableClass> vecSource;
vecSource.push_back(mc);
vecSource.push_back(mc);
Run Code Online (Sandbox Code Playgroud)
根据您的输出,发生以下情况:
vector设置为0.push_back调用:将mc复制插入到新分配的内存存储(复制构造函数).push_back调用:mc尝试复制插入.容量vector太小,因此分配了新的存储空间.将副本mc插入到新存储(复制构造函数)中.然后,将其余元素移动到新的内存位置(Move构造函数).我不认为附加元素的复制构造在标准强制重新定位之前的顺序,它只是在你正在使用的libstdc ++中实现它的方式.
附注:
宁愿-std=c++11到-std=c++0x如果编译器支持前者.
您不应该重用已经移过的实例.我希望你这样做只是为了测试目的.