Luk*_*ens 24 c++ rvalue-reference move-constructor c++11
我一直在测试一些C++ 11的一些功能.我遇到了r值引用并移动构造函数.
我实现了我的第一个移动构造函数,这里是:
#include <iostream>
#include <vector>
using namespace std;
class TestClass{
public:
TestClass(int s):
size(s), arr(new int[s]){
}
~TestClass(){
if (arr)
delete arr;
}
// copy constructor
TestClass(const TestClass& other):
size(other.size), arr(new int[other.size]){
std::copy(other.arr, other.arr + other.size, arr);
}
// move constructor
TestClass(TestClass&& other){
arr=other.arr;
size=other.size;
other.arr=nullptr;
other.size=0;
}
private:
int size;
int * arr;
};
int main(){
vector<TestClass> vec;
clock_t start=clock();
for(int i=0;i<500000;i++){
vec.push_back(TestClass(1000));
}
clock_t stop=clock();
cout<<stop-start<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常.无论如何把一个std :: cout放在复制构造函数中我注意到它被调用了!并且很多次..(移动构造函数500000次,复制构造函数524287次).
让我感到惊讶的是,如果我从代码中注释掉复制构造函数,整个程序会更快,而这次移动构造函数被称为1024287次.
任何线索?
How*_*ant 33
穿上noexcept你的移动构造函数:
TestClass(TestClass&& other) noexcept {
Run Code Online (Sandbox Code Playgroud)
详细说明:我打算给这一个皮埃尔,但不幸的是,cppreference源只是大致正确.
在C++ 03中
vector<T>::push_back(T)
Run Code Online (Sandbox Code Playgroud)
有"强烈的例外保证".这意味着如果push_back抛出异常,向量将保持与调用之前相同的状态push_back.
如果移动构造函数抛出异常,则此保证会出现问题.
当vector重新分配,就喜欢到移动的元素从旧的缓冲区,以新的.但是,如果这些移动中的任何一个抛出异常(除了第一个),那么它将处于旧缓冲区已被修改的状态,并且新缓冲区尚未包含它应该包含的所有内容.在vector旧的缓冲区不能恢复到原来的状态,因为它会移动元素回做,这些举动也可能会失败.
因此为C++ 11制定了一条规则:
如果T有一个noexcept移动构造函数,可用于将元素从旧缓冲区移动到新缓冲区.
否则,如果T有一个复制构造函数,将使用它.
否则(如果没有可访问的拷贝构造函数),则毕竟将使用移动构造函数,但是在这种情况下,不再给出强异常安全保证.
澄清:规则2中的"复制构造函数"是指构造函数const T&,而不是那些所谓的T&复制构造函数.:-)
Pie*_*aud 14
使用noexcept您的移动构造函数:
TestClass(TestClass&& other) noexcept { ... }
Run Code Online (Sandbox Code Playgroud)
noexcept没有像这样的常量表达式相当于noexcept(true).
编译器可以使用此信息对非抛出函数启用某些优化,并启用noexcept运算符,该运算符可以在编译时检查是否声明了特定表达式抛出任何异常.
例如,如果元素的移动构造函数是noexcept,则std :: vector等容器将移动它们的元素,否则复制.
资料来源:http://en.cppreference.com/w/cpp/language/noexcept_spec
注意:这是一个C++ 11功能.某些编译器可能还没有实现它...(例如:Visual Studio 2012)
| 归档时间: |
|
| 查看次数: |
2978 次 |
| 最近记录: |