二十一、C++中的临时对象
思考:
构造函数是一个特殊的函数
- 是否可以直接调用?
- 是否可以在构造函数中调用构造函数?
- 直接调用构造函数的行为是什么?
答:
直接调用构造函数将产生一个临时对象
临时对象的生命周期只有一条语句的时间
临时对象的作用域只在一条语句中
临时对象是C++中值得警惕的灰色地带
#include <stdio.h>
class Test {
int mi;
public:
Test(int i)
{
mi = i;
}
Test()
{
Test(0);
// 调用Test(int i),得到了一个临时对象,生命周期只有这句话,过了之后临时对象就被析构,临时对象没有名字,作用域也只有这句话,过了之后,不能再被访问。这里的临时对象几乎就没有作用。这个0根本就没有设置到mi上
}
// 等价于
Test(){
};
void print() {
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}
// 解决办法
// 提供一个私有的init函数,做初始设置
class Test {
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i) {
printf("Test(int i)\n");
init(i);
}
Test(){
printf("Test()\n");
init(0); // 调用的普通私有函数,不会产生临时对象
};
void print() {
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
printf("main begin\n");
Test(); // 直接调用构造函数,会产生一个临时对象
Test(10); // 产生临时对象
printf("main end\n")
return 0;
}
/*结果
main begin
Test()
~Test()
Test(int i)
~Test()
*/
int main()
{
printf("main begin\n");
Test().print(); // Test()结果是一个临时对象,是一个合法的对象,然后操作它的成员函数
Test(10); // 产生临时对象
printf("main end\n")
return 0;
}
/*结果
main begin
Test()
mi = 0 // 临时对象的打印
~Test()
Test(int i)
mi = 10 // 临时对象的打印
~Test()
*/
编译器的行为:现代C++编译器在不影响最终执行结果的前提下,会尽力减少临时对象的产生!!!
#include <stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test(const Test& t)
{
printf("Test(const Test& t) : %d\n", t.mi);
mi = t.mi;
}
Test()
{
printf("Test()\n");
mi = 0;
}
int print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
Test func()
{
return Test(20); // 应该是返回一个临时对象
}
int main()
{
Test t(10);
Test t = Test(10); // 1、生成一个临时对象;2、用临时对象初始化t
// ==> 调用拷贝构造函数
// 但是结果并没有打印拷贝构造函数,说明编译器没有生成临时变量
// 原因是现代编译器都会尽量减少临时变量的产生,
// 编译器将这句话等价成了 Test t(10)
// 临时变量的产生会带来性能上的问题
t.print();
Test tt = func();
tt.print(); // 会打印出20
/*
理论上应该是要调用拷贝构造函数,但是没有
编译器将这句话等价成了 ==> Test tt = Test(20) ==> Test tt = 20;
*/
return 0;
}
小结
直接调用构造函数将产生一个临时对象
临时对象是性能的瓶颈,也是BUG的来源之一
现代C++编译器会尽力避开临时对象
实际工程开发中需要认为地避开临时对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具