C++ 堆栈分配对象的指针和引用
假设我有以下代码(可能过于简单,但我认为它不够): 问题是&(o.a)可能会在以后指向任何东西,因为o的地址在返回时可能已更改(调用move或copy构造函数)。现在我发现大多数时候&(o.a)是相同的,因此调用*(o.b.a_ptr)不会导致segfault。(我认为这是由于RVO,因为RVO没有移动)。无论如何,只要我不确定o的地址没有改变,这个代码就不正确 一个显而易见的解决方案是要求动态分配我的BigObject:C++ 堆栈分配对象的指针和引用,c++,c++11,C++,C++11,假设我有以下代码(可能过于简单,但我认为它不够): 问题是&(o.a)可能会在以后指向任何东西,因为o的地址在返回时可能已更改(调用move或copy构造函数)。现在我发现大多数时候&(o.a)是相同的,因此调用*(o.b.a_ptr)不会导致segfault。(我认为这是由于RVO,因为RVO没有移动)。无论如何,只要我不确定o的地址没有改变,这个代码就不正确 一个显而易见的解决方案是要求动态分配我的BigObject: auto o_ptr = make_unique<BigObjec
auto o_ptr = make_unique<BigObject>();
auto o_ptr=make_unique();
这个解决方案还不错(没有泄漏,解决了前面的问题),但是我仍然觉得它不雅观:我不需要动态分配,我只需要为我的BigObject设置一个固定地址。我认为这将是Java做事情的方式。
另一个解决方案是在B中使用副本,但o.a中的所有更改都不会影响o.B.a,我不希望这样
第三种解决方案是在B中没有A的副本、ptr或引用,并将A传入方法B::someMethodUsingA()的参数。但是,在调用此函数时,查找要传递的参数可能会非常繁琐。有时候,B类有一个指向a类的指针感觉更自然
现在我发现这个问题在我的代码中反复出现:我想构建一个复杂的对象,其中子对象相互引用。根本的问题是,对象没有“就地”创建,它可能会在构建过程中稍后移动(但不是在构建完所有内容之后)
他们是否有任何已知的模式可以应用于此?我想这是一个相当普遍的问题,如果不是,那一定是因为我没有以正确的方式构建我的系统
有没有办法确保某种RVO?我的意思是,由标准来保证,而不是由编译器来保证。类似于编译器警告“BigObject”不能移动到其他地址
我还想删除move和copy-ctor以及赋值操作符,但是我无法按值返回一个对象,即使实际上什么都没有移动
欢迎分享对您有用的内容!将A引用参数添加到B的函数中,当BigObject调用函数时,它可以传递其A。A和B应该是私有的。如有必要,将包装函数添加到BigObject,重定向到对A和B的调用,并根据需要传递A参数
不要编写需要RVO才能工作的代码。我不明白为什么需要在struct
BigObject
中使用struct对象及其指针。
您可以这样设计结构:
struct A { ... };
struct BigObject {
A a;
MyOtherClass someMethodUsingA() { /* Here you can use the variable a. */ }
};
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;
}
};
如果仍要按自己的方式编码,可以为struct BigObject
添加复制构造和分配构造函数,如下所示:
struct A { ... };
struct BigObject {
A a;
MyOtherClass someMethodUsingA() { /* Here you can use the variable a. */ }
};
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;
}
};
关于A和B是私有的:别担心,它们在我的实际代码中是私有的。现在正如我所解释的,使用您的解决方案对我来说似乎很乏味。在这种情况下,没有大问题,但假设as和B是BigObject的子成员,那么问题就来了:您必须添加getA()在每个子成员中,您必须有一个对包含对象的引用…@BérengerBerthoul听起来您的设计有问题。您的类在层次结构中布局,但是子对象需要上下很多次才能相互通信。如果我不使用将对象作为f传递的解决方案,我就不会有这个问题函数参数。如果层次结构中的一个对象持有指向层次结构中另一个对象的指针,但位于完全不同的位置,则无需在层次结构中上下移动。OK,我设法使用了一些接近您答案的内容。我添加了一个move-ctor/assignment,而不是copy。目前代码不太干净(因为几个不相关的问题)但它应该在经过一些思考后再做。关于添加B类的必要性:在这个玩具示例中,不太多,但在实际代码中,B和BigObject中都有许多方法,我想分离责任一个评论:有人发现自己处于这种情况吗(使用ptr移动对象)?我在代码中一次又一次地找到它,但如果没有其他人这样做,我可能只是在构建对象的方式上出错了。