您好,欢迎来到好走旅游网。
搜索
您的当前位置:首页关于C++ 11的右值

关于C++ 11的右值

来源:好走旅游网

右值的概念

右值的使用

  1. 右值应用的一般是为了解决一些临时数据拷贝问题
  2. 做法一般也是直接拷贝右值的内存地址,不做深度拷贝,并放弃右值对该内存引用
  3. 移动拷贝:其实就是使用以上方法构造一个新对象
class MoveConClass {
public:

	MoveConClass(){}

	~MoveConClass() {
		if (str) {
			delete[] str;
			str = nullptr;
		}
	}

	MoveConClass(const char* t) {
		if (t) {
			int count = strlen(t)+1;
			str = new char[count];
			strcpy_s(str, count, t);
		}
	}

	// 拷贝函数,一般需要处理深度拷贝
	MoveConClass(const MoveConClass& a) {
		k = a.k;
		if (a.str) {
			int c = strlen(a.str) + 1;
			str = new char[c];
			strcpy_s(str, c, str);
		}
		test_int = a.test_int;
		std::cout << "MoveConClass(const MoveConClass& a)" << k << std::endl;
	}

    // 移动构造,浅拷贝,并且右值指针置空,避免右值释构时释放该内存
	MoveConClass(MoveConClass&& a) noexcept: str(a.str){
		a.str = nullptr;
		k = a.k;
		test_int = std::move(a.test_int);
		std::cout << "MoveConClass(MoveConClass&& a)" << k<< ", "<< str << std::endl;
	}

	int k = 0;
	char* str = nullptr;
	std::vector<int> test_int;
};

实现移动构造实现后,我们就可以利用该特性,处理一些数据快速拷贝,例如我们处理对该对象operator+的处理

static MoveConClass operator+(const MoveConClass& a, const MoveConClass& b) {
	MoveConClass d;
	int a_count = strlen(a.str);
	int count = a_count + strlen(b.str) +1;
	d.str = new char[count];
	strcpy_s(d.str, count, a.str);
	strcpy_s(d.str + a_count, count - a_count, b.str);
	d.test_int.insert(d.test_int.end(), a.test_int.begin(), a.test_int.end());
	d.test_int.insert(d.test_int.end(), b.test_int.begin(), b.test_int.end());
	return d;
}

实际使用时可以写如下代码

	MoveConClass a("this is ");
	a.test_int = { 12,12,12,1,24,233 };
	MoveConClass b("a test");
	b.test_int = { 34,34, 5, 6, 1213 };
	MoveConClass c = a + b;

右值的常见函数

  1. std::move(value) 用于把一个左值变成右值类型:一般为触发与右值相关函数计算

实现方式类似于强转: static_cast<T&&>(value)

  1. std::forward(value) 按类型返回对应的左值或右值类型:一般为解决函数参数为右值类型,但函数中使用却被认为是左值的问题

实现方式类似于在对应类型上进行&&操作,如果T是左值,则是&&转化后,变右值,如果是T是右值,“右值的右值会变左值”。

右值使用注意

  1. 右值类型作为函数参数时,在函数内,该值还是会被视作为左值, 可以结合std::forward来解决。
template <typename T>
static void test_copy(T&& a) {
	std::cout << "inside test copy!!" << std::endl;
	MoveConClass b = std::forward<T>(a);
	std::cout << "the b is :s" << b;
}
  1. 使用“移动”构造后,右值相关的内存引用一定要去掉,避免右值释放掉相关内存。

右值使用的优缺点

纯个人理解,欢迎批评

  1. 使用移动构造后,就不必在函数中传入目标对象的指针或引用,通过函数返回的右值,可以较优雅都解决数据拷贝的问题,并且不会产生很大的开销。
// 一般避免数据拷贝的方法
A a;// 先创建A
create_a_data(&a); // 传入指针或引用
// 使移动构造后, 可以这样写
A a = create_a_data();
  1. 缺点也有,右值使用给人较大迷惑性,尤其右值在函数中多次传递后,很容易搞不清楚该右值什么时候已经失效了。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- haog.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务