問題は、それは、あなたがA
ためのコピーコンストラクタ/代入演算子を定義していないとB
への割り当ては、少なくとも代入演算子(コンパイラによって生成され、この場合、デフォルトの1、)を呼び出し以来ということです単に返された 'A'インスタンスからポインタa
をコピーします。その後、そのインスタンスが削除されるとメモリは解放され、のメンバーはB
になり、ゴミを指すようになります。
#include <cstdio>
class A
{
public:
int *a;
A()
{
a = new int;
printf("A::A(0x%p): a is 0x%p\n", this, a);
*a = 22;
}
A foo()
{
A anA;
*anA.a = 44;
return anA;
}
~A()
{
printf("A::~A(0x%p): a is 0x%p\n", this, a);
delete a;
}
};
int main(int argc, char** argv)
{
A B;
B = B.foo();
}
が出力:
だから、適切なコピーコンストラクタ/代入演算子を実装する、またはそれらの1 /削除の両方を作るのいずれかあなたは少しのログを追加した場合、それを見ることは容易です生ポインタを使用してコピーをエスケープする。たとえば、A(const A&) = delete;
とA& operator=(const A&) = delete;
を追加すると、プログラムがコンパイルされず、コピーが行われる場所にどのようにアプローチするかを調べ始めることができます。
最も大きな問題はセマンティクスです。
#include <cstdio>
class A
{
public:
int *a;
A()
{
a = new int;
printf("A::A()(0x%p): a is 0x%p\n", this, a);
*a = 22;
}
A(const A& otherA)
{
a = new int;
printf("A::A(const A& otherA)(0x%p): a is 0x%p\n", this, a);
*a = *otherA.a;
}
A& operator=(const A& otherA)
{
printf("A::operator=(const A& otherA)(0x%p)\n", this);
// What are the semantics here? Transfer ownership? Copy Value?
*a = *otherA.a;
return *this;
}
A foo()
{
A anA;
*anA.a = 44;
return anA;
}
~A()
{
printf("A::~A(0x%p): a is 0x%p\n", this, a);
delete a;
}
};
int main(int argc, char** argv)
{
{
A B;
B = B.foo();
printf("B.a is %d\n", *B.a);
}
return 0;
}
ただし、コピー操作のセマンティクスはどのようなものでしょうか?ポインタの所有権を移しますか?値をコピーしますか?コンパイラはこれらのクラスには答えられないので、メンバーをコピーするだけです。
あなたの質問には、クラスにデストラクタがある場合、ほぼ確実にコピーコンストラクタと代入演算子も必要です。 –
あなたがすることは*未定義の動作*につながるので、あなたは*何でも*期待できます。これに限定されないが、[鼻悪魔](http://catb.org/jargon/html/N/nasal-demons.html)を含む。ほとんどの場合、クラッシュするだけです。右値または左値があるかどうかは関係ありません。 –
@NeilButterworthによるコメントを拡大するには、[3,5、および0のルール](http://en.cppreference.com/w/cpp/language/rule_of_three)を読んでください。 –