網站首頁 編程語言 正文
一、初探臨時對象
1.問題
下面的程序輸出什么?為什么?
下面編寫程序進行實驗:
#include <stdio.h>
class Test {
int mi;
public:
Test(int i) {
mi = i;
}
Test() {
Test(0);
}
void print() {
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}
輸出結果如下:
程序意圖:
- 在 Test() 中以 0 作為參數調用 Test(int i)
- 將成員變量 mi 的初始值設置為 0
運行結果:
- 成員變量 mi 的值為隨機值
2.思考
構造函數是一個特殊的函數
- 是否可以直接調用?
- 是否可以在構造函數中調用構造函數?
- 直接調用構造函數的行為是什么?
3.答案
- 直接調用構造函數將產生一個臨時對象
- 臨時對象的生命周期只有一條語句的時間(過了這條 C++ 語句,臨時對象將被析構而不復存在)
- 臨時對象的作用域只在一條語句中
- 臨時對象是 C++ 中值得警惕的灰色地帶
可以將上面代碼寫成這樣,避免臨時對象:
#include <stdio.h>
class Test {
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i) {
init(i);
}
Test() {
init(0);
}
void print() {
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}
輸出結果如下:
再來看一個程序,深刻體會一下臨時對象:
#include <stdio.h>
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;
}
輸出結果如下:
這個程序很好的說明了臨時對象的生命周期只有一條語句的時間(過了這條 C++ 語句,臨時對象將被析構而不復存在)
二、編譯器的行為
現代 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);
Test t = Test(10); // ==> Test t = 10;
Test tt = func(); // ==> Test tt = Test(20); ==> Test tt = 20;
t.print();
tt.print();
return 0;
}
輸出結果如下:
注意兩點:
- 通過輸出結果可以看到【編譯器并沒有按照生成臨時對象,再用臨時對象初始化 t 對象(其中涉及調用拷貝構造函數)】的步驟,因為現代的編譯器都會盡力避免臨時對象的產生。
- Test t = Test(10); 等價于 Test t = 10; 寫成Test t = 10; 可以杜絕臨時對象的產生。因為臨時對象的產生會帶來性能上的問題,Test t = Test(10); 相當于調用了兩次構造函數, 而 Test t = 10; 少調用一次函數,性能得到提升。
三、小結
- 直接調用構造函數將產生一個臨時對象
- 臨時對象是性能的瓶頸,也是 bug 的來源之一
- 現代 C++ 編譯器會盡力避開臨時對象
- 實際工程開發中需要人為的避開臨時對象
原文鏈接:https://blog.csdn.net/weixin_43129713/article/details/124188079
相關推薦
- 2022-10-23 react優雅處理多條件鼠標拖拽位移_React
- 2023-06-18 C#中如何連接海康威視_C#教程
- 2022-05-21 Python?requests用法和django后臺處理詳解_python
- 2022-12-14 Python如何對音視頻文件進行解析詳解_python
- 2022-04-26 ASP.NET?Core中的Razor頁面實現路由功能_實用技巧
- 2022-06-06 flutter 導航組件 AppBar (含頂部選項卡TabBar,抽屜菜單 drawer ,自定義
- 2022-10-02 Blender?Python編程創建發光材質示例詳解_python
- 2023-05-31 python升級pip及失敗處理方式_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支