我試圖做到這一點:
#include <iostream>
#include <memory>
class B
{
public:
std::string var;
B()
{
var = "original";
}
void print()
{
std::cout << "composition " << std::endl;
}
};
class A
{
public:
int a_attribute = 10;
std::unique_ptr<B> b;
};
int main()
{
A a;
a.b->print();
}
這似乎作業正常,除非我嘗試訪問 B 的屬性,例如:
std::string test = a.b->var;
導致segmentation fault錯誤
為什么我沒有收到錯誤a.b->print();但收到段錯誤a.b->var;?
uj5u.com熱心網友回復:
你的問題就在這里,在 A 你有
std::unique_ptr<B> b;
這將創建一個指向 B 物件的智能指標。但是它沒有指向它的B物件。在你可以使用它之前,你必須創建一個 B 物件并設定 'b' 指向它。
我不知道你想如何以及何時創建你的 B 但你可以這樣做
A a;
a.b = std::make_unique<B>();
a.b->print();
這將使用默認建構式創建一個新的 B 并使其指向“ab”。這是更有效的簡寫
A a;
B *b1 = new B;
a.b.reset(b1);
a.b->print();
它顯式地創建了一個 B 然后將 ab 設定為指向它。
請注意,您不必釋放 B 物件。這就是智能指標的重點,他們會為你做這件事。
您問為什么有些組合有效而有些無效。
你有未定義的行為。這可以做任何事情,包括最糟糕的,似乎作業。然后在圣誕節前夜的午夜,你最大的客戶向你的系統提交了一個大訂單,然后它就崩潰了。每個專業開發人員都遇到過這種情況。避免的方法:提高編譯器警告級別,永遠不要忽略警告。使用 valgrind 之類的工具或其他商業檢查工具。
對我來說,您發布的原始代碼有效。為什么,因為呼叫的方法實際上不需要 B 物件中的任何資料。但是如果我改成這個
void print()
{
std::cout << "composition " << std::endl;
std::cout << var << std::endl;
}
它失敗了,因為現在我們正在參考 B 物件中的資料,但沒有。
請注意,在不同的編譯器上,您的原始代碼將不起作用
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/431676.html
