[C++]通过构造函数体会右值引用

在下面的构造函数和等号重载中,分别使用了左值的方式和右值的方式
可以看到,右值的方式相比左值,少了拷贝操作,性能更优

源代码

#include "pch.h"
#include<iostream>
#include <stdio.h>
using namespace std;
int cnt = 0;
class myc
{
	int id=0;//对象id,只在构造时自增
	char* str;//没有实际内容,只用来分配空间和展示地址
	size_t s;//内存大小
public:
	void show()
	{
		cout << "	id: " << id << endl;
		cout <<"	address: " << &str << endl;
		cout << "	size_t: " << s << endl;
		cout << "--------------------------------------------------" << endl;
	}
	myc(size_t x)
	{
		id = ++cnt;
		cout << "	构造:" << id<<endl;
		str = new char[x];
		s = x;
	}
	~myc()
	{
		cout << "	析构:" <<id<< endl;
		if (str != nullptr)
		{
			delete[] str;
			str = nullptr;
		}
		s = 0;
	}
	myc(const myc& tmp)
	{
		id = ++cnt;
		cout << "	拷贝构造:" << tmp.id<<" copy to " << id << endl;
		s = tmp.s;
		str = new char[s];
		memcpy(str, tmp.str, tmp.s *sizeof(char));
	}
	myc(myc&& tmp)
	{
		id = ++cnt;
		cout << "	移动构造:" <<tmp.id<<" move to "<<id << endl;
		s = tmp.s;
		str = tmp.str;
		tmp.str = nullptr;
		tmp.s = 0;
	}
	myc& operator=(myc& tmp)
	{
		cout << "	copy left " <<tmp.id<<" to "<<id << endl;
		if (str != nullptr && this != &tmp)
		{
			delete[] str;
		}
		s = tmp.s;
		str = new char[s];
		memcpy(str, tmp.str, tmp.s * sizeof(char));
		return *this;
	}
	myc& operator=(myc&& tmp)
	{
		cout << "	copy right " <<tmp.id<<" to " << id << endl;
		if (str != nullptr && this != &tmp)
		{
			delete[] str;
		}
		str = tmp.str;
		s = tmp.s;
		tmp.str = nullptr;
		tmp.s = 0;
		return *this;
	}
};
myc getTmp(size_t ll)
{
	return ll > 0 ? myc(ll) : myc(100);

}
int main()
{
	cout << "操作 a:" << endl;
	myc a(10);
	cout << "show a:" << endl;
	a.show();
	cout << "操作 b:" << endl;
	myc b(a);
	cout << "show b:" << endl;
	b.show();
	cout << "操作 c:" << endl;
	myc c(5);
	cout << "show c:" << endl;
	c.show();
	//这里是拷贝赋值操作
	cout << "操作 c=a:" << endl;
	c = a;
	cout << "show c:" << endl;
	c.show();
	//这里是搬运赋值操作,右值引用
	//为b赋了getTmp返回的临时变量(右值)
	cout << "操作 b=getTmp(100):" << endl;
	//这里会有两次析构是因为重载的=中包含一次删除操作,这会触发析构函数
	b = getTmp(100);
	cout << "show b:" << endl;
	b.show();
	cout << "操作 myc d=getTmp(20):" << endl;
	myc d = getTmp(20);
	cout << "show d:" << endl;
	d.show();
	cout << "end" << endl;
	return 0;
}
}

运行结果

在这里插入图片描述
在这里插入图片描述

<think>好的,我现在要回答用户关于C++引用是否会调用构造函数的问题。首先,我需要理解用户的问题核心。用户想知道在使用引用时,是否会触发构造函数的调用,尤其是移动构造函数或其他类型的构造函数。 根据提供的引用内容,特别是引用[3]和[4],引用主要用于实现移动语义,其中移动构造函数是一个关键部分。移动构造函数接受引用作为参数,允许资源的所有权转移,而不是深拷贝,这可以提高效率。例如,当使用std::move将左转换为时,会调用移动构造函数,如引用[2]中的示例代码所示,其中fun(std::move(x))将x转为,但构造函数是否被调用要看是否有对应的移动构造函数定义。 另外,引用[5]提到,当默认拷贝构造函数被删除时,可以定义移动构造函数来进行移动构造,这说明引用确实会调用移动构造函数,前提是存在这样的构造函数。如果类中没有移动构造函数,即使使用引用,也可能调用拷贝构造函数,尤其是在编译器无法自动生成移动构造函数的情况下。 需要注意的是,引用本身并不会直接导致构造函数的调用,而是根据上下文中的对象初始化或赋操作来决定。例如,当使用引用初始化一个新对象时,如果有移动构造函数可用,就会调用它;否则,可能会回退到拷贝构造函数,或者编译错误,如引用[5]所述的情况。 总结来说,引用是否调用构造函数取决于是否有对应的移动构造函数,以及使用场景。如果存在移动构造函数,并且使用引用初始化对象时,就会调用移动构造函数,否则可能调用拷贝构造函数或导致错误。</think>在C++中,引用本身不会直接触发构造函数的调用,但**引用的使用场景**(如对象初始化、赋或参数传递)可能会调用特定类型的构造函数。以下是具体分析: --- ### 1. **引用构造函数的关系** 引用(`&&`)主要与**移动构造函数**和**移动赋运算符**相关联。当用初始化新对象时,若存在移动构造函数,则会优先调用它: ```cpp class MyClass { public: MyClass() {} // 默认构造函数 MyClass(MyClass&& other) { // 移动构造函数 // 资源转移(非拷贝) } }; MyClass obj1; MyClass obj2 = std::move(obj1); // 调用移动构造函数 [^4] ``` 此处`std::move(obj1)`将左转换为,触发移动构造函数的调用。 --- ### 2. **引用不一定会调用构造函数** 引用的本质是**类型声明**,其行为取决于具体使用场景: - **绑定到临时对象**:直接引用现有对象,不触发构造函数。 ```cpp int&& r = 10; // 引用直接绑定到字面量,无构造函数调用 ``` - **作为函数参数**:仅影响重载决议,函数内部逻辑决定是否构造对象。 ```cpp void func(MyClass&& obj) { // 参数是已存在的对象,不触发构造 // 使用obj } ``` --- ### 3. **与其他构造函数的交互** - **无移动构造函数时**:若未定义移动构造函数引用可能回退到**拷贝构造函数**(如果可用)[^5]。 - **强制调用移动构造**:通过`std::move`显式转换左,可触发移动构造[^2]。 --- ### 4. **关键区别:移动构造 vs 拷贝构造** | 特性 | 拷贝构造函数 | 移动构造函数 | |---------------------|---------------------|---------------------| | 参数类型 | `const T&` | `T&&` | | 资源处理 | 深拷贝 | 资源转移(浅拷贝) | | 性能影响 | 较高 | 较低 | | 触发条件 | 左初始化 | 初始化 | --- ### 5. **应用场景与优化** 引用通过避免不必要的拷贝提升性能,例如: - 函数返回临时对象时触发移动语义[^4]。 - 容器操作(如`std::vector::push_back`)利用移动构造优化资源管理[^1]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值