Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 堆栈分配对象的指针和引用_C++_C++11 - Fatal编程技术网

C++ 堆栈分配对象的指针和引用

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

假设我有以下代码(可能过于简单,但我认为它不够):

问题是&(o.a)可能会在以后指向任何东西,因为o的地址在返回时可能已更改(调用move或copy构造函数)。现在我发现大多数时候&(o.a)是相同的,因此调用*(o.b.a_ptr)不会导致segfault。(我认为这是由于RVO,因为RVO没有移动)。无论如何,只要我不确定o的地址没有改变,这个代码就不正确

一个显而易见的解决方案是要求动态分配我的BigObject:

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移动对象)?我在代码中一次又一次地找到它,但如果没有其他人这样做,我可能只是在构建对象的方式上出错了。