C++11学习笔记 -- move、auto、decltype、for

本文介绍了C++11中的新特性,包括右值引用、void std::move()函数的应用,自定义拷贝构造函数及赋值运算符,类型推导结合模板的使用,以及范围for循环等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cassert> 
#include <typeinfo>

using namespace std;


//C++11 右值引用和void std::move()函数
//右值:在 = 的右边,没名称,没法取地址,只是一个字面值或临时变量
//左值:在 = 的左边,有名称,可以取地址

////1. move只是将参数转为右值,本身并不会提升性能和改变原来的内容
////  一般在某个对象或者数据需要放入容器,但不想再拷贝一份数据,使用move会提升性能
////2. 右值作为类的拷贝构造函数、赋值运算符的参数,可以不进行资源的深拷贝,
////  直接将对象的指针拿过来并还原被拿者为初始状态,从而减少拷贝消耗的性能
//// (不懂,需要这样拷贝或者赋值,为啥不直接使用原来那个对象呢)
void testMove()
{
	//str1有名称,可以取地址,是左值;“1234”无名称,无法取地址,是右值
	string str1 = "1234";
	vector<string> vec;
	vec.push_back(str1);//复制一份放入容器
	cout << str1 << endl;//普通左值,原来的数据还在
	//vec.push_back(move(str1));//STL容器支持右值操作,不复制,直接将当前的数据放入容器
						 //并使当前的数据为初始状态,此时性能有所提升
	string str2 = move(str1);//string的拷贝构造支持右值操作,str1内容将被拿走并初始状态
	cout << str1 << endl;
}

//C++11 如果类中存在内存管理,需要自定义:
//		析构函数(防止资源泄漏)
//		拷贝构造函数(防止浅拷贝)
//		赋值运算符(同上)
//		右值拷贝
//		右值赋值
class MyClass
{
public:
	//构造函数
	MyClass(const char* str)
	{
		int len = strlen(str) + 1;
		m_str = new char[len];
		memset(m_str, 0, len);
		memcpy_s(m_str, len - 1, str, len - 1);
		cout << " is constructor :" << m_str << endl;
	}
	//拷贝构造函数
	MyClass(const MyClass& l)
	{
		int len = l.getLen() + 1;
		m_str = new char[len];
		memset(m_str, 0, len);
		memcpy_s(m_str, len - 1, l.getData(), len - 1);
		cout << " is l copy constructor " << m_str << endl;
	}
	//右值拷贝(右值拷贝结束时,参数需要变成初始状态)
	MyClass(MyClass&& r)
	{
		m_str = r.getData();
		r.setData(nullptr);
		cout << " is r copy constructor " << m_str << endl;
	}
	//赋值运算符
	MyClass& operator = (const MyClass& m)
	{
		if (this == &m)
		{//自赋值
			return *this;
		}
		//释放原来的资源
		if (m_str) delete m_str;
		//创建空间,拷贝数据
		int len = m.getLen() + 1;
		m_str = new char[len];
		memset(m_str, 0, len);
		memcpy_s(m_str, len - 1, m.getData(), len - 1);
		cout << " is l equal constructor " << m_str << endl;
		return *this;
	}
	//右值赋值运算符
	MyClass& operator = (MyClass&& m)
	{
		if (this == &m)
		{//自赋值
			return *this;
		}
		int len = m.getLen() + 1;
		m_str = new char[len];
		memset(m_str, 0, len);
		memcpy_s(m_str, len - 1, m.getData(), len - 1);
		m.setData(nullptr);
		cout << " is r equal constructor " << m_str << endl;
		return *this;
	}
	~MyClass()
	{ 
		if(m_str)
			delete m_str;
	}
	
public:
	int getLen() const { return strlen(m_str); }
	char *getData() const
	{ 
		assert(m_str);
		return m_str;
	}
	void setData(const char* str)
	{
		if (str == nullptr)
		{//右值拷贝的时候,直接改值,不要释放资源
			m_str = nullptr;
			return;
		}
		delete m_str;
		int len = strlen(str) + 1;
		m_str = new char[len];
		memset(m_str, 0, len);
		memcpy_s(m_str, len - 1, str, len - 1);
	};

private:
	char *m_str = nullptr;
};

void testClass()
{
	MyClass m("1234");//构造
	MyClass a = m;//拷贝构造
	MyClass n = move(m);//右值拷贝构造
	//cout << m.getData() << endl;//error m 被右值后资源被初始化,不能再访问资源
	m = a;//赋值运算符
	n = move(a);//右值赋值运算符
}

//C++11 类型推导结合使模板的定义和使用更加简单
template<typename A, typename B>
auto add(A a, B b) -> decltype(a + b)
{
	return a + b;
}
//错误,此时的a和b还未定义decltype(a + b)无法推导
//template<typename A, typename B>
//decltype(a + b) add(A a, B b)
//{
//	return a + b;
//}

void testAuto()
{
	//C++11 类型推导
	//auto 类型推导必须定义时就初始化
	auto a = char('a');//auto = char
	cout << a << "  " << typeid(a).name() << endl;
	auto b = 'b';//auto = char
	cout << b << "  " << typeid(b).name() << endl;
	auto c = "c";//auto = const char *
	cout << c << "  " << typeid(c).name() << endl;
	auto d = const_cast<char *>("d");//auto = char *
	cout << d << "  " << typeid(d).name() << endl;
	auto e = string("e");//std::string
	cout << e << "  " << typeid(e).name() << endl;
	auto f = 102;//auto = int
	cout << (char)f << "  " << typeid(f).name() << endl;
	//decltype 类型推导的表达式中的数据必须是已定义的
	decltype(f) g;
	g = 103;
	cout << (char)g << "  " << typeid(g).name() << endl;
	auto h = new int(104);
	cout << (char)*h << "  " << typeid(h).name() << endl;
	auto i = add(1.01, 2.0);
	cout << "i = " << i << " " << typeid(i).name() << endl;
}

//C++11 范围for循环
void testFor()
{
	int array[10] = { 0,1,2,3,4,5,6,7,8,9 };
	//旧的访问方式,用下标以引用的方式访问数组
	for (int i = 0; i < sizeof(array) / sizeof(int); ++i)
	{
		cout << array[i] << " ";
	}
	cout << endl << "******************************************" << endl;
	//C++11
	for (auto i : array)
	{//按值访问,容器内的数据不会被修改,但是每个元素都会被临时创建,影响性能
		cout << i << " ";
	}
	cout << endl << "******************************************" << endl;
	for (auto& i : array)
	{//按引用访问,不会创建临时对象,但容器内的数据可以被修改
		cout << i << " ";
	}
	cout << endl << "******************************************" << endl;
	for (const auto& i : array)
	{//按const引用访问,不会创建临时对象,容器内的数据也不可以被修改
		cout << i << " ";
	}
	cout << endl << "******************************************" << endl;
}

int main()
{
//	testMove();
//	testClass();
//	testAuto();
	testFor();
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值