IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++对象优化 -> 正文阅读

[C++知识库]C++对象优化

1. 对象使用过程中背后调用了哪些方法

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a=10):ma(a)
	{
		cout << "Test(int)" << endl;
	}
	~Test()
	{
		cout << "~Test()" << endl;
	}
	Test(const Test& t) :ma(t.ma)
	{
		cout << "Test(const Test& t)" << endl;
	}
	Test& operator=(const Test& t)
	{
		cout << "operator=" << endl;
		ma = t.ma;
		return *this;
	}

private:
	int ma;
};
int main()
{
	Test t1;
	Test t2(t1);
	Test t3 = t1;
	
	//Test(20)显示生成临时对象 生存周期:所在语句
	/*
	C++编译器对于对象构造的优化:用临时对象生成新对象的时候,临时对象就不产生了,直接构造新对象就可以了
	*/
	Test t4 = Test(20);//Test t4(20);没有区别
	cout << "--------------------" << endl;
	t4 = t2;
	//显式生成临时对象
	t4 = Test(30);
	t4 = (Test)30;
	//隐式生成临时对象
	t4 = 30;
	cout << "---------------------" << endl;
	Test *p = &Test(40);
	//p指向的是一个已经析构的临时对象
	const Test& ref = Test(50);
	cout << "---------------------" << endl;
	return 0;
}

在这里插入图片描述

C++编译器对于对象构造的优化:用临时对象生成新对象的时候,临时对象就不产生了,直接构造新对象就可以了

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a=5,int b=5):ma(a),mb(b)
	{
		cout << "Test(int,int)" << endl;
	}
	~Test()
	{
		cout << "~Test()" << endl;
	}
	Test(const Test& src) :ma(src.ma), mb(src.mb)
	{
		cout << "Test(const Test& src)" << endl;
	}
	void operator=(const Test& src)
	{
		ma = src.ma;
		mb = src.mb;
		cout << "operator=" << endl;
	}

private:
	int ma;
	int mb;
};
Test t1(10, 10);
int main()
{
	Test t2(20, 20);
	Test t3 = t2;
	static Test t4 = Test(30, 30);
	t2 = Test(40, 40);
	t2 = (Test)(50, 50);
	t2 = 60;
	Test* p1 = new Test(70, 70);
	Test* p2 = new Test[2];
	//Test* p3 = &Test(80, 80);
	const Test& p4 = Test(90, 90);
	delete p1;
	delete[]p2;
}
Test t5(100, 100);

在这里插入图片描述

2. 函数调用过程中对象背后调用的方法

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a = 10) :ma(a)
	{
		cout << "Test(int)" << endl;
	}
	~Test()
	{
		cout << "~Test()" << endl;
	}
	Test(const Test& t) :ma(t.ma)
	{
		cout << "Test(const Test& t)" << endl;
	}
	Test& operator=(const Test& t)
	{
		cout << "operator=" << endl;
		ma = t.ma;
		return *this;
	}
	int getData()const
	{
		return ma;
	}
private:
	int ma;
};
Test GetObject(Test t)//不能返回局部的或者临时对象的引用或指针
{
	int val = t.getData();
	Test tmp(val);
	return tmp;
}
int main()
{
	Test t1;
	Test t2;
	t2 = GetObject(t1);
	return 0;
}

在这里插入图片描述
不能返回局部的或者临时对象的引用或指针

3. 对象优化的规则

  • 函数参数传递过程中,对象优先按引用传递,不要按值传递
Test GetObject(Test &t)
{
	int val = t.getData();
	Test tmp(val);
	return tmp;
}

在这里插入图片描述

  • 函数返回对象的时候,应该优先返回一个临时对象,而不要返回一个定义过的对象
    在这里插入图片描述

  • 接受返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收
    在这里插入图片描述

4. CMyString

代码问题

#include <iostream>
using namespace std;

class String
{
public:
    String(const char* str = nullptr)
    {
        cout << "String(const char*)" << endl;
        if (str != nullptr)
        {
            m_data = new char[strlen(str) + 1];
            strcpy(m_data, str);
        }
        else
        {
            m_data = new char[1];
            *m_data = '\0';
        }
    }
    String(const String& src)
    {
        cout << "String(const String& src)" << endl;
        m_data = new char[strlen(src.m_data) + 1];
        strcpy(m_data, src.m_data);
    }
    ~String()
    {
        cout << "~String()" << endl;
        delete[]m_data;
        m_data = nullptr;
    }

    //调用String&是为了支持连续的operator=赋值操作
    String& operator=(const String& src)
    {
        cout << "operator=" << endl;
        if (&src == this)
        {
            return *this;
        }
        delete[]m_data;
        m_data = new char[strlen(src.m_data) + 1];
        strcpy(m_data, src.m_data);
        return *this;
    }

    const char* c_str() {
        return m_data;
    }
private:
    char* m_data;//用于保存字符串
};

String get_string(String& str) {
    const char* pstr = str.c_str();
    String tmp(pstr);
    return tmp;
}

int main() {
    String str1("11111111111111111");
    String str2;
    str2 = get_string(str1);
    cout << str2.c_str() << endl;
    return 0;
}

添加带右值引用参数的拷贝构造和赋值函数

	 // 临时对象(右值)会匹配到右值引用为参数的函数,这里的src是临时对象(右值)
    String(String&& src){
        cout << "String(const String&& src)" << endl;
        m_data = src.m_data;
        src.m_data = nullptr;
    }
    
    String& operator=(String&& src){
        cout << "operator=(String&& src)" << endl;
        if (&src == this)
        {
            return *this;
        }
        delete[]m_data;
        m_data = src.m_data; // 改变堆区资源指向
        src.m_data = nullptr; // 临时对象的指针置空,防止析构的时候释放资源
        return *this;
    }

CMyString在vector上的应用
在这里插入图片描述

5.move和forward

std::move:移动语义,得到右值类型
std::forward:类型的完美转发,得到真实的左/右值

   //void construct(T* p, const T& val)//负责对象构造
    //{
    //    new(p)T(val);//定位new
    //}
    //void construct(T* p, T&& val)//负责对象构造
    //{
    //    new(p)T(std::move(val));//定位new
    //}
    

    template<typename Ty2>
    void construct(T* p, Ty2&& val)//负责对象构造
    {
        new (p) T(std::forward<Ty2>(val));//定位new
    }


	
    //void push_back(const T& val)//向容器末尾添加元素
    //{
    //    if (full())
    //        expand();
    //    //*_last++ = val;//last指针指向的内存构造一个值为val的对象
    //    _allocator.construct(_last, val);
    //    _last++;

    //}
    //void push_back(T&& val)//向容器末尾添加元素
    //{
    //    if (full())
    //        expand();
    //    //*_last++ = val;//last指针指向的内存构造一个值为val的对象
    //    _allocator.construct(_last, std::move(val));
    //    _last++;
    //}
    
    // 函数模板的类型推演 + 引用折叠
    // String&& + && = String&&
    // String& + && = String&
    // T char
    // Ty1 String

    template<typename Ty1> // 换个名会进行类型推演,直接用T直接断定是右值引用
    void push_back(Ty1&& val) 
    {
        if (full())
         {
            expand();
        }
        // forward:类型的完美转发
        _allocator.construct(_last, std::forward<Ty1>(val));
        _last++;
    }

函数模板的类型推演 + 引用折叠

String&& + && = String&&

String& + && = String&

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 10:40:43  更:2021-09-10 10:42:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 13:05:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计