[英]Pointers and references to stack-allocated object
假設我有以下代碼(可能被簡化了,但我認為足夠了):
struct BigObject {
A a;
B b;
};
struct A { ... };
struct B {
A const* a_ptr;
MyOtherClass someMethodUsingA() { ... }
}
class BigObjectBuilder {
BigObject build() {
BigObject o;
o.a = buildA();
o.b.a_ptr = &(o.a);
return o;
}
}
問題在於&(oa)稍后可能指向任何內容,因為返回o的地址可能已更改(調用move或copy構造函數)。 現在我發現&(oa)在大多數情況下都是相同的,因此調用*(oba_ptr)不會導致段錯誤。 (我認為這是由於RVO所致,因為那時o未被移動)。 無論如何,只要我不確定o的地址沒有更改,此代碼就是不正確的。
一個明顯的解決方案是要求動態分配我的BigObject:
auto o_ptr = make_unique<BigObject>();
這個解決方案還不錯(沒有泄漏,並且解決了先前的問題。),但是我仍然覺得它很不完善:我不需要動態分配,我只需要為BigObject提供一個固定地址即可。 我認為這將是Java的處理方式。 另一種解決方案是在B中使用副本,但是oa中的所有更改都不會影響oba,而我也不想這樣做。
第三種解決方案是在B中沒有A的副本,ptr或引用,並在方法B :: someMethodUsingA()的參數中傳遞A。 但是,再次找到調用此函數時要傳遞的參數可能很繁瑣。 有時,讓B類擁有指向A類的指針感覺更自然。
現在,我在代碼中一次又一次地發現了這個問題:我想構建一個復雜的對象,並且子對象之間相互引用。 根本的問題是該對象不是“就地”創建的,它可能會在以后的構建過程中移動(但並非在構建完所有東西之后)。
他們是否有適用於此的已知模式? 我想這是一個非常普遍的問題,如果不是,那一定是因為我沒有以正確的方式構建系統...
有沒有辦法確保某種RVO? 我的意思是,由標准而非編譯器保證。 像編譯器警告說“ BigObject”不能移到其他地址之類的東西”
我還考慮過刪除移動復制ctor和賦值運算符。 但是,即使在實踐中什么都沒有移動,我也無法按值返回對象。
歡迎為您工作的任何份額!
我不明白為什么在struct BigObject
需要一個struct對象及其指針。 您可以這樣設計結構:
struct A { ... };
struct BigObject {
A a;
MyOtherClass someMethodUsingA() { /* Here you can use the variable a. */ }
};
如果仍然想用自己的方式進行編碼,則可以為struct BigObject
添加copy-construct和assign-construct函數,如下所示:
struct BigObject
{
A a;
B b;
// copy-construct function
BigObject(const BigObject& old)
{
a = old.a;
b = old.b;
b.a_ptr = &a; // pay attetion
}
// assign construct function
BigObject& operator=(const BigObject& old)
{
if (this == &old) // avoid self-assignment
{
return *this;
}
a = old.a;
b = old.b;
b.a_ptr = &a;
return *this;
}
};
在B的函數中添加A引用參數,然后BigObject調用函數時,它可以傳遞其A。A和B應該是私有的。 如有必要,將包裝函數添加到BigObject,該函數將重定向到對A和B的調用,並根據需要傳遞A參數。
不要編寫要求RVO起作用的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.