c++11 移动构造_移动赋值_拷贝构造_拷贝赋值调用时机探究

c++11 移动构造_移动赋值_拷贝构造_拷贝赋值调用时机探究


最近对准备深入学习一下c++11所有的新特性,今天研究了一下c++11的std:move和std:forward,在研究这个的时候,需要对c++0xx的拷贝构造,拷贝赋值有一些了解.这个不知道的自己去了解,这里记录一下c++11新加的移动版本
移动构造_移动赋值和拷贝构造_拷贝赋值的比较,文章引用 现代c++之移动构造, 移动赋值, 拷贝构造, 拷贝赋值
的这篇文章来测试.
下面代码在vs2017上面可直接运行

#pragma once
#include <string>
#include <iostream>
#include <memory>
#include <vector>

class CMyString {
private:
	char * buf;
	int len;

private:
	void copy(const char* s) {
		buf = new char[len + 1];
		memcpy(buf, s, len);
		buf[len] = '\0';
	}

public:
	CMyString() {
		std::cout << "构造函数" << ",this:" << this << std::endl;

		buf = nullptr;
		len = 0;
	}

	CMyString(const char* str = nullptr) {
		if (str == nullptr) {
			std::cout << "构造函数" << ",this:" << this << std::endl;

			buf = nullptr;
			len = 0;
		}
		else {
			std::cout << "构造函数" << str << ",this:" << this << std::endl;
			len = strlen(str);
			copy(str);
		}
	}

	CMyString(const CMyString& str) {
		std::cout << "拷贝构造函数" << str.buf << ",this:" << this << ",right:" << &str << std::endl;

		len = str.len;
		copy(str.buf);
	}

	CMyString(CMyString&& str) {
		std::cout << "移动构造函数" << str.buf << ",this:" << this << ",right:" << &str << std::endl;

		//也可以直接使用std::move

		len = str.len;
		buf = str.buf;



		str.len = 0;
		str.buf = nullptr;
	}

	CMyString& operator=(const CMyString& str) {
		std::cout << "拷贝赋值函数" << str.buf << ",this:" << this << ",right:" << &str << std::endl;

		if (&str != this) {
			if (buf != nullptr) {
				delete[] buf;
				buf = nullptr;
			}

			len = str.len;
			copy(str.buf);
		}

		return *this;
	}



	CMyString& operator=(CMyString&& str) {
		std::cout << "移动赋值函数" << str.buf << ",this:" << this << ",right:" << &str << std::endl;

		if (this != &str) {

			if (buf != nullptr) {
				delete[] buf;
				buf = nullptr;
			}

			len = str.len;
			buf = str.buf;
			str.len = 0;
			str.buf = nullptr;
		}

		return *this;
	}

	~CMyString() {
		if (buf == nullptr)
		{
			std::cout << "析构函数" << ",this:" << this << std::endl;
		}
		else
		{
			std::cout << "析构函数" << buf << ",this:" << this << std::endl;
			delete[] buf;
			buf = nullptr;
		}
	}

	void print() {
		if (buf != nullptr)
			std::cout << buf << std::endl;
		else
			std::cout << "buf is null" << std::endl;
	}


};

void func1(CMyString str) {

}

CMyString func2() {
	CMyString s("34");//先构造一个CMyString
	return s; 
	/*返回前还会调用拷贝构造函数,或者拷贝赋值,中的一种作为返回值给调用者,或者如果定义了
	移动构造函数,移动赋值函数,那就会调用相应的移动版本函数*/
}

void test0() {
	CMyString s1("12");

	func1(s1); //函数func1值传递,对象str尚未初始化,会调用拷贝构造函数,func1调用结束会调用析构函数

	//func1(std::move(s1)); 
	/*函数func1值传递,对象str尚未初始化,会调用移动构造函数,但是后面还要
	用到s1,所以不能使用move,func1调用结束会调用析构函数*/

	CMyString s2 = func2(); 
	/* 对象s2尚未初始化,会产生临时对象,因func2返回的临时对象属于右值,调用移动构造函数,
	如果未定义移动构造函数会调用拷贝构造函数,func2调用结束会调用析构函数*/


	CMyString s3 = "56";

	s3 = s1; //对象s3已初始化,会调用拷贝赋值函数

	//函数调用结束,先析构s3,然后析构s2,再析构s1
}

void test1() {
	CMyString s4 = "781";
	CMyString s5 = "782";

	std::vector<CMyString> v1;
	v1.push_back(s4);//调用拷贝构造函数
	v1.push_back(std::move(s5)); // 对象尚未初始化,会调用移动构造函数

	std::cout << "开始输出v1\n";
	for (auto& str : v1)
		str.print();

	std::vector<CMyString> v2;
	v2 = std::move(v1);//调用move后,v1的内存被释放,相当于swap
	//v1.swap(v2);


	std::cout << "开始输出v1\n";
	for (auto& str : v1) //move后,v1中的内存被释放,size为0
		str.print();

	std::cout << "开始输出v2\n";
	for (auto& str : v2)
		str.print();
}

void test2() {

	CMyString s5 = "9";
	s5 = func2(); // 对象s5已初始化, 会产生临时对象,属于右值,调用移动赋值函数

	/*
运行结果:
构造函数9,this:009EFB48   ****1
构造函数34,this:009EFA34  ****2
移动构造函数34,this:009EFA78,right:009EFA34   ****3
析构函数,this:009EFA34   ****4
移动赋值函数34,this:009EFB48,right:009EFA78   ****5
析构函数,this:009EFA78   ****6
析构函数34,this:009EFB48  ****7

1:构造s5
2:构造func2中的临时对象s
3:调用移动构造函数构造临时对象
4:析构临时对象s
5:调用移动赋值函数赋值给s5
6:析构临时对象s
7:析构s5
	*/
}

//测试结合容器和智能指针使用的情况
void test3()
{
	CMyString s1 = "test3_s1";
	CMyString s2 = "test3_s2";

	//vector < shared_ptr<CMyString>> v1;
	//v1.push_back(make_shared<CMyString>(s1));
	//v1.push_back(make_shared<CMyString>(move(s2)));
	//v1.push_back(make_shared<CMyString>("test3_s3"));

	vector < shared_ptr<CMyString>> v2;
	v2.push_back(move(make_shared<CMyString>(s1)));
	v2.push_back(move(make_shared<CMyString>(move(s2))));
	v2.push_back(make_shared<CMyString>("test3_s3"));
}

int test_new()
{
	std::cout << "begin test0()" << std::endl;
	test0();
	std::cout << std::endl;

	std::cout << "begin test1()" << std::endl;
	test1();
	std::cout << std::endl;

	std::cout << "begin test2()" << std::endl;
	test2();

	std::cout << "begin test3()" << std::endl;
	test3();

	return 0;
}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值