?博主介紹:程序喵大人
- 35- 資深C/C++/Rust/Android/iOS客戶端開發
- 10年大廠工作經驗
- 嵌入式/人工智能/自動駕駛/音視頻/游戲開發入門級選手
- 《C++20高級編程》《C++23高級編程》等多本書籍著譯者
- 更多原創精品文章,首發gzh,見文末
- 👇👇記得訂閱專欄,以防走丟👇👇
😉C++基礎系列專欄
😃C語言基礎系列專欄
🤣C++大佬養成攻略專欄
🤓C++訓練營
👉🏻個人網站
最近訓練營里有同學問:
那拷貝構造函數不加引用會怎么樣呢?
貼段代碼:
#include <iostream>
class A {public: A() {std::cout << "A \n";}~A() {std::cout << "~A \n";}// A(const A& a) { // std::cout << "A(const& A) \n"; // } A(const A a) { std::cout << "A(const A) \n";}A& operator=(const A& a) {if (&a == this) {return *this;}std::cout << "operator= \n";return *this;}
};
編譯結果如圖:
可以看到,如果拷貝構造函數不加引用,編譯都會失敗的,那為什么編譯器要這樣限制,為什么一定要加引用呢?
拷貝構造函數的參數必須是引用,因為如果不是,我們將不得不通過值傳遞對象。通過值傳遞對象將需要拷貝對象,這將調用拷貝構造函數。
這會導致拷貝構造函數調用的無限循環,而通過使用引用,就可以避免這個無限循環,因為引用不會創建新對象,而是指向現有對象的內存位置。
考慮以下帶有接受引用參數的拷貝構造函數的類:
class MyClass {
public:int a;// 常規構造函數MyClass(int value) : a(value) {}// 接受引用參數的拷貝構造函數MyClass(const MyClass &obj) {a = obj.a;}
};
int main() {MyClass original(5); // 調用常規構造函數MyClass copy(original); // 調用接受引用參數的拷貝構造函數
}
在這個例子中,創建copy
對象時,調用了拷貝構造函數,并且它接受對original
對象的引用。這避免了無限循環問題,因為引用簡單地指向現有對象的內存位置,并且在過程中沒有創建新對象。
如果不加引用:
MyClass(MyClass obj) {a = obj.a;
}
這將在拷貝時導致無限循環,因為:
-
通過值傳遞時會創建一個新對象。
-
創建新對象需要調用拷貝構造函數
-
調用拷貝構造函數需要通過值傳遞對象,導致步驟1。
通過在拷貝構造函數中使用引用參數,可以防止這種無限循環,因為在傳遞引用時不會創建新對象。
所以編譯器直接在源頭就規避了這種問題,防止我們多踩坑。
???碼字不易,歡迎大家點贊,關注,評論,謝謝!
C++訓練營
專為校招、社招3年工作經驗的同學打造的1V1 C++訓練營,量身定制學習計劃、每日代碼review,簡歷優化,面試輔導,已幫助多名學員獲得大廠offer!