C++ Primer 第十三章 13.6 对象移动 练习和总结

13.6 对象移动

这一节本质上是对性能进行优化,(对设计资源管理的类的性能优化),就算不知道这一节的的内容,一样的可以编码,但是如果设计的类对性能要求较高,就需要这一节的内容了。

在使用vector装自定义的类型的类型时,如果容量不足会开辟空间,将原来的元素拷贝到新的空间的,原来的元素会被销毁,我们知道原来的元素拷贝到新空间之后,不会再使用,如果对象非常的大,那么拷贝是会消耗比较大的性能的,既然原来的对象拷贝之后就不再使用,那么有没有什么方法,能够让原本对象的内容直接拷贝到新的内存空间中呢,C++提供了移动操作,用来将原来对象“移动”到新的内存空间中。使用移动的方式可以避免拷贝

目前看来,“移动”操作和swap()类型可以大幅度提升性能的前提是类中有标准库容器,或者有指针指向的动态分配的对象。

13.6.1 右值引用

因为要支持移动操作,C++定义了右值引用。

使用&&来获取右值引用,有了右值引用,我们就可以其绑定的资源“移动”到另一个对象中

右值引用用来绑定字面值常量,返回右值的表达式以及要求转换类型的表达式 , (要求转换类型的意思应该是表达式中既有左值也有右值)

左值具有持久的状态,直到离开作用域才被销毁,而右值是字面值常量要么是表达式中的临时对象,所引用的对象即将被销毁且没有其他的用户。

所有的变量都是左值,因为右值引用的变量也是左值,而左值不能直接使用右值绑定。

需要使用std::move(obj)将左值转化为右值类型,但是这样意味着obj的资源将被右值引用的变量所接管,后续除了对obj进行赋值和销毁,我们不要再使用它。

练习
13.45

一句话:
左值引用可以绑定左值,const 左值引用和右值引用可以绑定右值。

左值引用可以绑定返回值类型为引用的函数、赋值、下标、解引用、前置递减递增运算符等返回左值的表达式的结果上。

const类型的左值引用和右值引用可以绑定在返回非引用类型的函数、算术、关系、位、后置递增递减等返回右值的表达式的结果上。

13.46
int &&r1 = f();
int &r2 = vi[0];
int & r3 = r1;
int &&r4 = vi[0] * f();
13.47

这里完善了之前的MyString类,添加了拷贝构造函数、拷贝内赋值运算符、free()等函数
.h文件

#pragma once
#include <memory>
class MyString {
   
	friend void print(std::ostream& s, const MyString& str);
public:
	MyString();
	MyString(const char*);
	MyString(const MyString&);
	MyString& operator=(const MyString&);
	~MyString();
	size_t size()const;
private:
	size_t get_char_arr_len(const char *);
	void free();
	static std::allocator<char> alloc;
	char* begin;
	char* end;
	char* last;
};

.cpp文件

#include "pch.h"
#include "MyString.h"
#include <algorithm>
#include <iostream>
using std::cout;
using std::endl;
std::allocator<char> MyString::alloc;


MyString::MyString()
{
   
	begin = alloc.allocate(1);
	alloc.construct(begin, '\0');
	end = begin;
	last = end + 1;
}

MyString::MyString(const char * c)
{
   
	size_t len = get_char_arr_len(c) + 1;
	begin = alloc.allocate(len);
	end = begin + len - 1;
	last = end + 1;
	size_t index = 0;
	for (auto iter = begin; iter != end; ++iter)
	{
   
		alloc.construct(iter, c[index]);
		++index;
	}
	*end = '\0';
}

MyString::MyString(const MyString & s)
{
   
	cout << "调用了拷贝构造函数" << endl;
	auto temp_begin = alloc.allocate(s.size() + 1);
	auto temp_iter = temp_begin;
	for (auto iter = s.begin; iter != s.end; ++iter)
	{
   
		alloc.construct(temp_iter
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值