您的位置:首页 > 编程语言 > C语言/C++

C++11新特性应用--让你的程序更高效(右值引用避免深拷贝)

2016-01-07 21:38 162 查看
这里的内容注意参考书籍《深入应用C++11代码优化与工程级应用》

今天,重温一下右值。

使用右值,使得我们的C++程序更加高效。

我们可以简单把右值理解为一个临时变量。之前,我们谁也不会在意这个临时变量,但要付出了效率的代价。

而右值引用就是对右值进行的引用类型,与我们通常所说的引用一样,一定要记得初始化。

左右值区分:

void func(X& x); // 左值引用 重载
void func(X&& x); // 右值引用 重载

X x;
X foobar();

func(x); // 参数为左值,调用func(X& x);
func(foobar()); // 参数为右值,调用func(X&& x);


再看看这个:

// lvalues:
//
int i = 42;
i = 43; // ok, i is an lvalue
int* p = &i; // ok, i is an lvalue
int& foo();
foo() = 42; // ok, foo() is an lvalue
int* p1 = &foo(); // ok, foo() is an lvalue

// rvalues:
//
int foobar();
int j = 0;
j = foobar(); // ok, foobar() is an rvalue
int* p2 = &foobar(); // error, cannot take the address of an rvalue
j = 42; // ok, 42 is an rvalue


之前在初始化列表的博客中提到过,使用初始化列表进行初始化,比在构造函数中初始化效率更高,道理是一样的。

这结论一定是正确的,当你用VS编译器试图写代码进行验证的时候,你也许就会骂娘了,这他妈输出结果不是一样的吗。

我只能呵呵了,因为编译器对程序进行了优化,你是看不到的。如果非要搞明白,就试图一步一步看看反汇编吧,包你满意。

下面就说说使用右值如何避免深拷贝。

此时,你可能又要犯嘀咕了?

深拷贝不是好事儿吗,使我们自己写的赋值构造函数实现深拷贝吗,是为了避免两个指针指向同一个东西,也避免删除同一个东西两次。

但,凡是都是在不停的发展的。因为C++11引入了右值概念,所以这就使得之前我们所写的赋值构造函数并不是那么完美了。主要还是效率的问题了。

下面就是用到了移动构造函数~之前也有提到过啊:

MyString(MyString&& str) {
std::cout <<"Move Constructor is called! source: "<< str._data << std::endl;
_len = str._len;
_data = str._data;         // 避免了不必要的拷贝
str._len = 0;
str._data = NULL;
}

MyString&operator=(MyString&& str) {
std::cout <<"Move Assignment is called! source: "<< str._data << std::endl;
if (this != &str) {
_len = str._len;
_data = str._data;    // 避免了不必要的拷贝
str._len = 0;
str._data = NULL;
}
return *this;
}


有了右值引用和移动语义,在设计和实现类时,对于需要动态申请大量资源的类,应该设计右值引用的拷贝构造函数和赋值函数,以提高应用程序的效率。需要注意的是,我们一般在提供右值引用的构造函数的同时,也会提供常量左值引用的拷贝构造函数,以保证移动不成还可以使用拷贝构造。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: