设为首页 加入收藏

TOP

C++中类的拷贝控制 与之相关的几个函数(二)
2015-07-20 17:53:40 来源: 作者: 【 】 浏览:4
Tags:拷贝 控制 相关 函数
复制代码

注意:析构函数不能是删除的成员,因为这样的类是无法销毁的。

如果一个类有const成员或者有引用成员,则这个类合成拷贝赋值运算符是被定义为删除的。

在新的标准出来之前,类是通过将其拷贝构造函数的拷贝赋值运算符声明为private来阻止拷贝,而且为了防止成员被友元或其他成员访问,会对这些成员函数只声明,但不定义。

7,右值引用

所谓的右值引用就是必须绑定在右值上的引用,我们可以通过&&来获得右值引用,右值引用一个很重要的性质是只能绑定到一个将要销毁的对象,所以我们可以自由地将一个右值引用的资源“移动”到另一个对象中。

我们可以将一个右值引用绑定到表达式上,但不能将右值引用绑定到一个左值上:

复制代码
int i = 42; 
int &r = i;        // 正确:r引用i 
int &&rr = i;    // 错误:不能将一个右值引用绑定到一个左值上 
int &r2 = i * 42;    // i*42是一具右值 
const int& r3 = i * 42;    // 可以将一个const的引用绑定到一个右值上 
int && rr2 = i * 42;    // 正确:将rr2绑定到乘法结果上
复制代码

总体来说:左值有持久的状态,而右值要么是字面常量,要么是表达式求值过程中创建的临时对象。

从而我们得知,关于右值引用:1)所引用的对象将要销毁;2)该对象没有其他用户。

标准库提供了一个std::move函数,让我们可以获得左值上的右值引用:

int  &&r3 = std::move(rr1); // rr1是一个变量

move调用告诉编译器:我们有一个左值,但是我们希望像一个右值一个处理它。在上面的代码后,要么销毁rr1,要么对rr1进行赋值,否则我们不能使用rr1。

另外一点值得注意的是,我们使用std::move而不是move,即使我们提供了using声明。

8,移动构造函数和移动赋值运算符

与拷贝一样,移动操作同样发生在我们一个类的对象去初始化或赋值同一个类类型的对象时,但是与拷贝不同的是,对象的内容实际上从源对象移动到了目标对象,而源对象丢失了内容。移动操作一般只发生在当这个源对象是一个uname的对象的时候。

一个uname object意思是一个临时对象,还没有被赋予一个名字,例如一个返回该类型的函数返回值或者一个类型转换操作返回的对象。

复制代码
MyClass fn();            // function returning a MyClass object
MyClass foo;             // default constructor
MyClass bar = foo;       // copy constructor
MyClass baz = fn();      // move constructor
foo = bar;               // copy assignment
baz = MyClass();         // move assignment 
复制代码

上面的代码中由fn()返回的对象和由MyClass构造出来的对象都是unnamed,用这样的对象给MyClass赋值或初始化时,并不需要拷贝,因为源对象只有很短的生命周期。

移动构造函数与移动赋值函数的定义形式上与拷贝操作一样,只是将拷贝函数的形参的引用换成右值引用。

MyClass (MyClass&&);             // move-constructor
MyClass& operator= (MyClass&&);  // move-assignment

移动操作对那些需要管理存储空间的类是非常有用的,比如我们下面定义的这个类

复制代码
// move constructor/assignment
#include 
  
   
#include 
   
     using namespace std; class Example6 { string* ptr; public: Example6 (const string& str) : ptr(new string(str)) {} ~Example6 () {delete ptr;} // move constructor Example6 (Example6&& x) : ptr(x.ptr) {x.ptr=nullptr;} // move assignment Example6& operator= (Example6&& x) { delete ptr; ptr = x.ptr; x.ptr=nullptr; return *this; } // access content: const string& content() const {return *ptr;} // addition: Example6 operator+(const Example6& rhs) { return Example6(content()+rhs.content()); } }; int main () { Example6 foo (Exam); Example6 bar = Example6(ple); // move-construction foo = foo + bar; // move-assignment cout << foo's content: << foo.content() << ' '; return 0; }
   
  
首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇构造数列Codeforces Round #261 (.. 下一篇POJ 1699 Best Sequence (DFS+预..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: