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

如果第二个对象是在复制或赋值结束后被销毁的临时对象,则调用移动构造函数和移动赋值运算符,这样的好处是避免深度复制,提高效率

为了直观地观察移动构造函数和移动赋值运算符的运行方式,编写一个类Pointer,该类的对象会在堆动态创建一个数组。

代码如下:

class Pointer
{
public:
	Pointer(const int i,const string &n)
	{
		mptr = new int[i];
		length = i;
		name = n;
		cout <<"带参数构造函数\n";
		showID();
	}
	Pointer() :mptr(nullptr), length(0){ cout << "无参数构造函数\n"; showID(); }
	virtual ~Pointer()
	{
		cout <<name+ "析构函数\n";
		if (mptr)
			delete[] mptr;
		mptr = nullptr;

	}

	Pointer(const Pointer& s)
	{
		length = s.getlen();
		mptr = new int[length];
		name = s.name;
		cout << "复制构造函数\n";
		showID();
	}
	Pointer& operator=(const Pointer &s)
	{
		if (this == &s)
			return *this;
		if (mptr)
			delete[] mptr;
		length = s.getlen();
		mptr = new int[length];
		name = s.name;
		cout << "赋值运算符\n";
		showID();
		return *this;
	}

	//移动构造函数,参数s不能是const Pointer&& s,因为要改变s的成员数据的值
	Pointer(Pointer&& s)
	{
		length = s.getlen();
		mptr = s.getmptr();
		name = s.name + "_yidonggouzao";//调用移动构造函数时,加一个标记
		s.mptr = nullptr;
		cout << "移动构造函数\n";
		showID();
	}

	//移动赋值运算符
	Pointer& operator=(Pointer&& s)
	{
		if (this == &s)
			return *this;
		if (mptr)
			delete[] mptr;
		length = s.getlen();
		mptr = s.mptr;
		name = s.name+"_yidongfuzhi";//调用移动赋值运算符时,加一个标记
		s.mptr = nullptr;
		cout << "移动赋值运算符\n";
		showID();
		return *this;
	}

	void showID()
	{
		cout << "长度:" << length<<"  指针:"<< mptr <<"  名字:"<<name<< endl;
	}

	int getlen() const
	{
		return length;
	}

	int* getmptr()const
	{
		return mptr;
	}

private:
	int* mptr;
	int length;
	string name="#NULL";//该参数用来标记不同的对象,c++11支持直接在类的数据成员定义处初始化
};

Pointer test()
{
	Pointer a(2,"test");
	return a;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//加花括号是为了观察析构函数的调用
	{
		Pointer(4,"notname1");//这条语句结束后,该变量马上被销毁,所以这是一个临时变量

		Pointer a1=test();//调用移动构造函数,创建对象a1
		cout << "a1.showID():\n";
		a1.showID();

		Pointer a2;
		a2=Pointer(5, "notname2");//调用移动赋值运算符

		Pointer a3(Pointer(7, "notname3"));//此处没有调用移动构造函数,<span style="font-family: Arial, Helvetica, sans-serif;">Pointer(7, "notname3") 这个变量没有被立即销毁(即不是临时变量了)</span>,也许是因为给它有了名字a3,所以<span style="font-family: Arial, Helvetica, sans-serif;">不是临时变量了</span>

		cout << "a3.showID():\n";
		a3.showID();//验证a3确实是Pointer(7, "notname3")
	}

	cout << endl;
	system("pause");
	return 0;
}

运行结果如下:

时间: 2024-12-14 17:53:47

移动构造函数和移动赋值运算符的相关文章

c++类的拷贝、赋值与销毁(拷贝构造函数、拷贝赋值运算符析构函数)

拷贝构造函数     如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数. 拷贝构造函数第一个参数必须是一个引用类型.此参数几乎总是一个const的引用.拷贝构造函数在几种情况下都会被隐式地使用.因此,拷贝构造函数通常不应该是explicit的. 合成拷贝构造函数 与合成默认构造函数不同,即使我们定义了其他构造函数,编译器也会为我们合成一个拷贝构造函数. 对某些类来说,合成拷贝构造函数用来阻止我们拷贝该类类型的对象.而一般情况,合成的拷贝构造函数

在String中添加移动构造函数和移动赋值运算符

13.50 没有定义析构函数 #include<iostream> #include<string> #include<memory> #include<utility> #include<cstring> #include<vector> using namespace std; class String { public: String():elements(nullptr),first_free(nullptr) {} Stri

第五篇:明确拒绝不想编译器自动生成的拷贝构造函数和赋值运算符重载函数

前言 如果你不想要编译器帮你自动生成的拷贝机制 (参考前文),那么你应当明确的拒绝. 如何拒绝?这便是本文要解决的主要问题. 问题描述 当你定义了一个类,而这个类中各对象之间也是封装的 - 禁止同类对象之间的相互赋值以及复制,那么你需要屏蔽掉编译器帮你生成的拷贝构造函数以及赋值运算符. 在许多代码中,会看到通过将拷贝构造函数和赋值运算符重载函数声明为私有且不予实现来实现这个功能.然而,这不是最科学的做法. 因为这没有做到真正的屏蔽:你在自己的成员函数中,或者友元函数中仍然可以调用这两个私有函数,

[QT入门篇]3 QObject的拷贝构造函数与赋值运算符

本文主要是针对QObject的拷贝构造函数和赋值运算符进行说明.先来看一下拷贝构造函数定义:拷贝构造函数,又称复制构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化.其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上const限制.此函数经常用在函数调用时用户定义类型的值传递及返回.拷贝构造函数要调用基类的拷贝构造函数和成员函数.如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用. 还记得<[QT入门篇]1 QT中的对象模型>中

明确拒绝不想编译器自动生成的拷贝构造函数和赋值运算符重载函数

前言 如果你不想要编译器帮你自动生成的拷贝机制 (参考前文),那么你应当明确的拒绝. 如何拒绝?这便是本文要解决的主要问题. 问题描述 当你定义了一个类,而这个类中各对象之间也是封装的 - 禁止同类对象之间的相互赋值以及复制,那么你需要屏蔽掉编译器帮你生成的拷贝构造函数以及赋值运算符. 在许多代码中,会看到通过将拷贝构造函数和赋值运算符重载函数声明为私有且不予实现来实现这个功能.然而,这不是最科学的做法. 因为这没有做到真正的屏蔽:你在自己的成员函数中,或者友元函数中仍然可以调用这两个私有函数,

c++拷贝构造函数、赋值运算符=重载、深拷贝与浅拷贝

 关键词:构造函数,浅拷贝,深拷贝,堆栈(stack),堆heap,赋值运算符 摘要: 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作. 如果对象在申明的同时马上进行的初始化操作,则称之为拷贝运算.例如: class1 A("af"); class1 B=A; 此时其实际调用的是B(A)这样的浅拷贝操作. 如果对象在申明之后,在进行的赋值运算,我们称之为赋值运算.例如: class1 A("af"); class1 B; B=A; 此时实际调用的类

拷贝构造函数与赋值运算符重载函数要点

拷贝构造函数 一个小例子 最近在<剑指Offer>上看到了一道题(程序如下),要求我们分析编译运行的结果,并提供3个选项: A. 编译错误: B. 编译成功,运行时程序崩溃:C. 编译运行正常,输出10. 1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 private: 7 int value; 8 9 public: 10 A(int n) { value = n; } 11 A(A other) {

c++--类的构造函数与拷贝控制

类(class)与结构体(struct)的位移区别在于:默认情况下,类的派生方式和访问权限是private的,struct的派生方式和访问权限是public的. 构造函数 构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数. 特点1:不同于其他成员函数,构造函数不能被声明为const的(参见7.1.2,P231). 当我们创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其"常量属性".因此,构造函数在const对象的构造过程中

赋值运算符、拷贝初始化和this指针

一.赋值运算符和拷贝构造函数(重载技术) 赋值运算符和拷贝构造函数有编译器默认提供,但如果想做更复杂的事,需要重载. 1.下面用一个简单的例子先区分一下赋值运算符和拷贝构造函数: #include<iostream> using namespace std; class  alpha { public:     alpha():data(0) {}       //没有参数的构造函数     alpha(int d):data(d) {}  //一个参数的构造函数     void dipla