C++ C++;初始化包含另一个对象设计问题的对象

C++ C++;初始化包含另一个对象设计问题的对象,c++,constructor,arguments,pass-by-reference,lvalue,C++,Constructor,Arguments,Pass By Reference,Lvalue,我试图编写两个类A和B,其中B包含类A的实例。实际上,A包含一些大数据。在这个玩具示例中,让我们假设它们如下所示: class A{ public: int a; A(){} A(const A& ac){ cout <<"copy constructor for A" << endl; a = ac.a; } virtual ~A(){} A& operator=(const A

我试图编写两个类
A
B
,其中
B
包含类
A
的实例。实际上,
A
包含一些大数据。在这个玩具示例中,让我们假设它们如下所示:

class A{
public:
    int a;
    A(){}
    A(const A& ac){
       cout <<"copy constructor for A" << endl;
       a = ac.a;
    }
    virtual ~A(){}
    A& operator=(const A& that){
      cout <<"operator = for A" << endl;
      a = that.a;
      return *this;
   }
};
class B{
private:
    A ba;
public:
    B(){  a = A();  }
    B(A& a){
        cout << "Using default constructor" << endl;
        ba = a;
    }
    B(const B& copy){
        cout<<"copy"<< endl; ba = copy.ba;
    }
    B& operator=( const B& that){
       cout<<"invoking operator = "<< k<< endl;
       ba = that.ba;
       return *this;
    }
    virtual ~B(){}
    A& getA(){ return ba; }
    void printAadrr(){
        cout << &ba <<" "<< ba.a<< endl;
    }
};
我可以

class B{
    private:
        A* ba;
public:
    B(){  
       ba = new A(); //but we have to free memory in destructor if we call default constructor
    }
    B(A& a){
        cout << "Using default constructor" << endl;
        ba = &a;
    }
但它给出了“左值必须在赋值的左边”错误


任何建议都将不胜感激。抱歉,这篇文章太长了。

与其将A作为简单的成员变量,不如使用指向A的指针。然后在构造B时,只需传递指向A实例的指针即可

class B{
private:
    A* ba;

与其将A作为简单的成员var,不如使用指向A的指针。然后在构造B时,只需将指针传递给A的实例

class B{
private:
    A* ba;

这取决于你的设计。如果您想要
B
own
A
使用
std::move
通过
B
获得
A

一般情况下,使用
std::shared_ptr
,它将自行管理内存。
std::shared_ptr
的所有实例都将被销毁后,
A
数据也将被删除。但是在这种情况下,
B
实例可以共享相同的
A
数据


另一种解决方案是
std::unique\u ptr
,但每次复制
B
时都必须移动它,这意味着
A
的所有权将与
std::move
解决方案一样转移。

这取决于您的设计。如果您想要
B
own
A
使用
std::move
通过
B
获得
A

一般情况下,使用
std::shared_ptr
,它将自行管理内存。
std::shared_ptr
的所有实例都将被销毁后,
A
数据也将被删除。但是在这种情况下,
B
实例可以共享相同的
A
数据


另一种解决方案是
std::unique\u ptr
,但每次复制
B
时都必须移动它,这意味着
A
的所有权将与
std::move
解决方案相同。

使用移动语义定义构造函数,如下所示:

B::B( A && a )
: ba( std::move( a ) )
{}
现在可以将实例转移到对象中

A a;
B b( std::move( a ) );
// `b` stores content of `a`, and local `a` is no longer valid.
如果需要,仍然可以使用复制构造函数进行构造


使用移动语义定义构造函数,如下所示:

B::B( A && a )
: ba( std::move( a ) )
{}
现在可以将实例转移到对象中

A a;
B b( std::move( a ) );
// `b` stores content of `a`, and local `a` is no longer valid.
如果需要,仍然可以使用复制构造函数进行构造


C++11提供了右值引用以及
std::move
,以明确您的意图。如果要将
A
转换为
B
,这将非常有用。否则,您可以自由地存储对外部对象的引用。但必须在构造函数中使用初始值设定项列表,而不是直接赋值。或者您可以使用
std::reference\u包装器
。注意在对象中存储引用,因为您可能会遇到对象生存期问题。。。谢谢你的“指针”。我不知道
std::move
std::reference\u包装器
。我将详细阅读。C++11提供了右值引用以及
std::move
,以明确您的意图。如果要将
A
转换为
B
,这将非常有用。否则,您可以自由地存储对外部对象的引用。但必须在构造函数中使用初始值设定项列表,而不是直接赋值。或者您可以使用
std::reference\u包装器
。注意在对象中存储引用,因为您可能会遇到对象生存期问题。。。谢谢你的“指针”。我不知道
std::move
std::reference\u包装器
。我会仔细阅读的。谢谢,但这是我的第二种方法,它有它自己的问题,正如这个方法中的问题所指出的,因为你在B中有一个指向a的指针,您不应该从B中创建对象A。拥有指针的全部意义在于它可以保存指向内存中已由程序另一部分创建的某个对象的链接。在本例中,主方法中已经实例化了。我不确定这是否适合您的设计。是的,
A
应该在主方法中启动,但是在默认构造函数的情况下,我不会在主方法中有一个现成的
A
对象,因此我必须寻找一种健壮的方法来创建
B
,无论
A
来自何处。明白了吗。我认为如果没有实例,最好将*初始化为null。另外,在使用*anywhere作为安全保护之前,请检查null。这一切都是为了取舍:)啊,说得好。我也想到了
NULL
,但有点犹豫是否使用它,因为正是您提到的原因(到处检查安全防护)。如果SO中没有给出有效答案,我打算使用这种方法+谢谢,但这是我的第二种方法,它有自己的问题,如本方法中的问题所示,因为你在B中有一个指向a的指针,您不应该从B中创建对象A。拥有指针的全部意义在于它可以保存指向内存中已由程序另一部分创建的某个对象的链接。在本例中,主方法中已经实例化了。我不确定这是否适合您的设计。是的,
A
应该在主方法中启动,但是在默认构造函数的情况下,我不会在主方法中有一个现成的
A
对象,因此我必须寻找一种健壮的方法来创建
B
,无论
A
来自何处。明白了吗。我认为如果没有实例,最好将*初始化为null。另外,在使用*anywhere作为安全保护之前,请检查null。这一切都是为了取舍:)啊,说得好。我也想到了
NULL
,但有点犹豫是否使用它,因为正是您提到的原因(到处检查安全防护)。我打算用这个