指针和堆栈分配对象的引用 [英] Pointers and references to stack-allocated object

查看:112
本文介绍了指针和堆栈分配对象的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I have the following code (it may be oversimplified but I think it will be enought) :

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;
    }
}

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

The problem is that &(o.a) may point to anything later on because o's address may have changed when it is returned (either the move or the copy constructor is called). Now I found that most of the time &(o.a) is the same so that calling *(o.b.a_ptr) won't result in a segfault. (I think this is due to RVO because then o is not moved). Anyway this code is not correct as long as I'm not sure that the address of o has not changed.

一个明显的解决方案是请求我的BigObject的动态分配:

An obvious solution would be to ask for a dynamic allocation of my BigObject:

auto o_ptr = make_unique<BigObject>();

这个解决方案不太糟糕(没有泄漏,解决了以前的问题。发现它inelegant:我不需要一个动态分配,我只需要一个固定的地址为我的BigObject。这将是我做的事情的Java方式我认为。
另一个解决方案是在B中使用一个副本,但是oa中的所有更改不会影响oba,我不想这样。

This solution is not too bad (no leaks, and solves the previous problem.), however I still found it inelegant: I don't NEED a dynamic allocation, I only need to have a fixed address for my BigObject. This would be the Java way of doing things I think. Another solution would be to use a copy in B, but then all changes in o.a won't affect o.b.a, and I don't want that.

第三个解决方案是在B中没有副本,ptr或A的引用,并且在方法B :: someMethodUsingA()的参数中传递A.但是再次,这可能是繁琐的,找到什么参数传递时调用此函数。有时候,B类有一个指向A类的指针,感觉更自然。

A third solution would be to have no copy, ptr or references of A in B, and passing A in argument of the method B::someMethodUsingA(). But again this could be tedious to find what argument to pass when calling this function. Sometimes it just feels more natural for the class B to have a pointer to class A.

现在我发现这个问题在我的代码中再次出现:我想构建一个复杂的对象,子对象相互引用。最基本的问题是对象不是就地创建的,它可以在构建过程中被移动(但不是在构建完所有对象之后)。

Now I found this problem happening again and again in my code: I want to build a complex object, with subobjects referencing each other. The fundamental problem is that the object is not created "in place", it may be moved later on during the build process (but not after everything has been built).

是他们任何已知的模式可以应用到这?我想这是一个相当普遍的问题,如果不是这一定是因为我不是建立我的系统正确的方法...

Is their any known pattern that can apply to this ? I suppose this is quite a common problem, and if not it must be because I am not building my system the right way...

有一种方法,以确保一些种RVO?我的意思是,由标准保证,而不是由编译器。类似编译器警告说BigObject不能移动到不同的地址

Is there a way to ensure some kind of RVO ? I mean, ensured by the standard, not by the compiler. Something like a compiler warning saying "BigObject" can't be moved to a different address"

我也想到删除移动和复制ctor和赋值运算符,我无法通过值返回对象,即使在实践中没有移动...

I also thought of deleting the move and copy ctor and assignment operator. But then I am unable to return an object by value, even if in practice nothing is moved...

欢迎任何对你有用的分享!

Any share of what is working for you is welcome !

推荐答案

我不明白为什么你需要一个struct对象及其指针在struct BigObject
你可以这样设计结构:

I can not understand why you need a struct object and its pointer in struct BigObject. You can design struct like this:

struct A { ... };
struct BigObject {
   A a;
   MyOtherClass someMethodUsingA() { /* Here you can use the variable a. */ }
};

如果你仍然想要以你的方式编码,你可以为 struct BigObject ,如下所示:

If you still want to code by your way, you can add copy-construct and assign-construct function for struct BigObject, like this:

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;
     }
};

这篇关于指针和堆栈分配对象的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆