C++ 初始化包含另一个对象设计问题的对象
C++ initializing an object that contains another object design issue
我正在尝试编写两个 classes A
和 B
,其中 B
包含 class 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;
}
};
问题在于,当使用 B::B(A& a)
初始化 B
时,参数被复制到 B
中的实例 ba
中。如果 a
很大,它可能效率低下。
我想到了另一种方法,而不是
class B{
private:
A ba;
....
我可以
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;
}
但是这种设计选择有其自身的问题,如果我将 B
作为默认构造函数,我需要在稍后的析构函数中释放分配给 ba
的内存。
如果我们使用 B::B(A& a)
并创建一个空的默认 A
对象,如果我们使用 B::B()?我试过了
B::B(A& a){
&ba = &a;
}
但它给出 "lvalue has to be on the left of assignment" 错误。
如有任何建议,我们将不胜感激。抱歉太长了 post.
不要将 A 作为简单的成员 var,而是要有指向 A 的指针。然后在构造 B 时,只需将指针传递给 A 的实例即可。
class B{
private:
A* ba;
这取决于您的设计。如果你想 B
拥有 A
使用 std::move
通过 B
获得 A
。
一般情况下使用std::shared_ptr
,它将自行管理内存。 std::shared_ptr<A>
的所有实例被销毁后,A
的数据也将被删除。但在这种情况下 B
个实例可以 共享 相同的 A
数据。
其他解决方案是 std::unique_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.
如果您想要,您仍然可以使用复制构造函数构造。
A a;
B b( a );
// `b` stores a copy of `a`, and local `a` is still valid.
我正在尝试编写两个 classes A
和 B
,其中 B
包含 class 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;
}
};
问题在于,当使用 B::B(A& a)
初始化 B
时,参数被复制到 B
中的实例 ba
中。如果 a
很大,它可能效率低下。
我想到了另一种方法,而不是
class B{
private:
A ba;
....
我可以
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;
}
但是这种设计选择有其自身的问题,如果我将 B
作为默认构造函数,我需要在稍后的析构函数中释放分配给 ba
的内存。
如果我们使用 B::B(A& a)
并创建一个空的默认 A
对象,如果我们使用 B::B()?我试过了
B::B(A& a){
&ba = &a;
}
但它给出 "lvalue has to be on the left of assignment" 错误。
如有任何建议,我们将不胜感激。抱歉太长了 post.
不要将 A 作为简单的成员 var,而是要有指向 A 的指针。然后在构造 B 时,只需将指针传递给 A 的实例即可。
class B{
private:
A* ba;
这取决于您的设计。如果你想 B
拥有 A
使用 std::move
通过 B
获得 A
。
一般情况下使用std::shared_ptr
,它将自行管理内存。 std::shared_ptr<A>
的所有实例被销毁后,A
的数据也将被删除。但在这种情况下 B
个实例可以 共享 相同的 A
数据。
其他解决方案是 std::unique_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.
如果您想要,您仍然可以使用复制构造函数构造。
A a;
B b( a );
// `b` stores a copy of `a`, and local `a` is still valid.