c++11 中的移动构造函数

在现实中有很多这样的例子,我们将钱从一个账号转移到另一个账号,将手机SIM卡转移到另一台手机,将文件从一个位置剪切到另一个位置……移动构造可以减少不必要的复制,带来性能上的提升。

l  C++11标准中提供了一种新的构造方法——移动构造。

l  C++11之前,如果要将源对象的状态转移到目标对象只能通过复制。在某些情况下,我们没有必要复制对象——只需要移动它们。

l  C++11引入移动语义:

n  源对象资源的控制权全部交给目标对象

l  移动构造函数

问题与解决

l  当临时对象在被复制后,就不再被利用了。我们完全可以把临时对象的资源直接移动,这样就避免了多余的复制操作。

移动构造

l  什么时候该触发移动构造?

n  有可被利用的临时对象

l  移动构造函数:

class_name ( class_name && )

例:函数返回含有指针成员的对象(版本1)

l  使用深层复制构造函数

返回时构造临时对象,动态分配将临时对象返回到主调函数,然后删除临时对象。

#include<iostream>
using namespace std;
class IntNum {
public:
   IntNum(int x = 0) : xptr(new int(x)){ //构造函数
         cout << "Calling constructor..." << endl;
   }
   IntNum(const IntNum & n) : xptr(new int(*n.xptr)){//复制构造函数
         cout << "Calling copy constructor..." << endl;
   };
   ~IntNum(){ //析构函数
         delete xptr;
         cout << "Destructing..." << endl;
   }
   int getInt() {   return *xptr;   }
private:
   int *xptr;
};

//返回值为IntNum类对象
IntNum getNum() {
   IntNum a;
   return a;
}
int main() {
   cout<<getNum().getInt()<<endl;
   return 0;
}
运行结果:
Calling constructor...
Calling copy constructor...
Destructing...
0
Destructing...

例:函数返回含有指针成员的对象(版本2)

l  使用移动构造函数

将要返回的局部对象转移到主调函数,省去了构造和删除临时对象的过程。

#include<iostream>
using namespace std;
class IntNum {
public:
      IntNum(int x = 0) : xptr(new int(x)){ //构造函数
           cout << "Calling constructor..." << endl;
      }
      IntNum(const IntNum & n) : xptr(new int(*n.xptr)){//复制构造函数
线形标注 3: 注:
?&&是右值引用
?函数返回的临时变量是右值
           cout << "Calling copy constructor..." << endl;
      }
      IntNum(IntNum && n): xptr( n.xptr){   //移动构造函数
           n.xptr = nullptr;
           cout << "Calling move constructor..." << endl;
      }
      ~IntNum(){ //析构函数
           delete xptr;
           cout << "Destructing..." << endl;
      }
private:
      int *xptr;
};

//返回值为IntNum类对象
IntNum getNum() {
IntNum a;
return a;
}
int main() {
cout << getNum().getInt() << endl; return 0;
}
运行结果:
Calling constructor...
Calling move constructor...
Destructing...
0
Destructing...

时间: 2025-01-01 20:50:25

c++11 中的移动构造函数的相关文章

C++11中的继承构造函数

时间:2014.06.19 地点:基地 ------------------------------------------------------------------------- 一.问题描述 在继承体系中,如果派生类想要使用基类的构造函数,需要在构造函数中显式声明.如下: struct A { A(int i){} }: struct B:A { B(int i):A(i){} }; 在这里,B派生于A,B 又在构造函数中调用A的构造函数,从而完成构造函数的传递. 又比如如下,当B中存

C++学习笔记18,C++11中的初始化列表构造函数(二)

C++11中的初始化列表构造函数(Initialize_list Constructors)是将std::initializer_list<T>作为第一个参数的构造函数,并且没有任何其他参数(或者其他参数具有默认值).例如: #include <iostream> #include <initializer_list>//必须包含该头文件 #include <vector> using namespace std; class A { private: ve

C++11中多线程库

一.linux 线程同步 线程是在操作系统层面支持的,所以多线程的学习建议还是先找一本linux系统编程类的书,了解linux提供多线程的API.完全完全使用系统调用编写多线程程序是痛苦,现在也有很多封装好的多线程库,但是了解多线程系统对学习编写多线程程序非常有好处.总的来说linux提供了四类系统用于多程序程序,分别线程的创建.销毁(thread),用于线程同步的(互斥量(mutex).条件量(cond),信号量(sem)). 互斥量通过锁的机制实现线程间的同步.互斥量是一种特殊的变量,可以对

【转载】C++ 11中的右值引用

本篇随笔为转载,原博地址如下:http://www.cnblogs.com/TianFang/archive/2013/01/26/2878356.html 右值引用的功能 首先,我并不介绍什么是右值引用,而是以一个例子里来介绍一下右值引用的功能: #include <iostream>    #include <vector>    using namespace std; class obj    {    public :        obj() { cout <&l

C++11中uniform initialization和initializer_list

C++11中出现了uniform initialization的概念: int a1 = {1};//ok int a2 = {1.0};//错误,必须收缩转换 int array1[] = {1,2,3,4};//ok int arrya2[] = {1.0,2.0,3.0,4.0};//ok 注意a2的初始化错误和array2的正确对比.一方面uniform initialization要求初始化的类型必须是一致的,但一方面新的C++标准必须兼容C++98,而在C++98中array2的初始

C++11中once_flag,call_once实现分析

本文的分析基于llvm的libc++,而不是gun的libstdc++,因为libstdc++的代码里太多宏了,看起来蛋疼. 在多线程编程中,有一个常见的情景是某个任务只需要执行一次.在C++11中提供了很方便的辅助类once_flag,call_once. 声明 首先来看一下once_flag和call_once的声明: struct once_flag { constexpr once_flag() noexcept; once_flag(const once_flag&) = delete

C++ 11 中的右值引用

C++ 11 中的右值引用 右值引用的功能 首先,我并不介绍什么是右值引用,而是以一个例子里来介绍一下右值引用的功能: #include <iostream>    #include <vector>    using namespace std; class obj    {    public :        obj() { cout << ">> create obj " << endl; }        obj(c

C++11中智能指针的原理、使用、实现

目录 理解智能指针的原理 智能指针的使用 智能指针的设计和实现 1.智能指针的作用 C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理.程序员自己管理堆内存可以提高了程序的效率,但是整体来说堆内存的管理是麻烦的,C++11中引入了智能指针的概念,方便管理堆内存.使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存. 理解智能指针需要从下面三个层次: 从较浅的层面看,智能指针是利用了一种叫做RAII(资

c++11 中的 move 与 forward

一. move 关于 lvaue 和 rvalue,在 c++11 以前存在一个有趣的现象:T&  指向 lvalue (左传引用), const T& 既可以指向 lvalue 也可以指向 rvalue.但却没有一种引用类型,可以限制为只指向 rvalue.这乍看起来好像也不是很大的问题,但其实不是这样,右值引用的缺失有时严重限制了我们在某些情况下,写出更高效的代码.举个粟子,假设我们有一个类,它包含了一些资源: class holder { public: holder() { res