將 C 物件傳遞到它自己的建構子中合法嗎?
像這樣的程式碼的功能令人困惑:
#include <iostream> struct Foo { Foo(Foo& bar) { std::cout << &bar << std::endl; } }; int main(int argc, char** argv) { Foo foo(foo); // I can't believe this works... std::cout << &foo << std::endl; // but it does... return 0; }
透過將未初始化物件的位址傳遞到自己的建構函式中,我們似乎正在建立一個循環定義。問題出現了:標準是否允許在建構物件之前將物件傳遞給函數?或者這是否構成未定義行為?
合法,但並不罕見
將未初始化物件的位址傳遞到其自己的建構函式中並不是未定義行為。雖然 foo 未初始化,但我們以標準批准的方式使用它。
物件記憶體分配發生在完全初始化之前。因此,在此時間間隔內允許綁定對此類變數的引用並檢索其位址。
此行為與缺陷報告 363 一致,該報告闡明在這種情況下創建的引用被視為有效。 C 14 標準的第 3.8 節 [basic.life] 進一步規定,在限制範圍內使用引用已指派但未初始化物件的泛左值是允許的。
也就是說,我們不能應用左值到右值轉換,存取非靜態資料成員或呼叫非靜態成員函數,綁定到虛擬基類引用,或使用dynamic_cast或typeid。
在我們的範例中,我們避免了這些禁止的操作,綁定引用並取得位址。
編譯器警告
儘管行為合法,Clang 仍會發出警告:
warning: variable 'foo' is uninitialized when used within its own initialization [-Wuninitialized]
此警告是合理的,因為未初始化的值會產生不確定的值自動變數構成未定義的行為。儘管如此,我們的使用不會產生不確定的值,因此是合法的。
進一步的考慮因素
雖然透過將物件傳遞給其自己的構造函數來進行自初始化本質上並不是無論是有益的還是可取的,它都可以成為探索階級行為的有趣的方法。然而,透過賦值進行自初始化,如 int x = x; ,確實構成了未定義的行為。
以上是將 C 物件傳遞到自己的建構函數中是否合法?的詳細內容。更多資訊請關注PHP中文網其他相關文章!