2017-02-25 7 views
0

行B = B.foo()の後に、B.aの値がどのように期待されますか。 ?クラスのポインタメンバーに、そのオブジェクトに右辺値を割り当てるとどうなりますか?

私はB.a = 44と予想しましたが、B.a = 0を得ました。それは理にかなっていますか?

class A { //here is a class A 
    public: 
    int *a; 

    A(){ a = new int; *a=22;} 

    A foo(){ A anA;  //anA is an object of the class A 
       *anA.a=44; 
       return anA; 
    } 

    ~A(){ delete a;} 

}; 

int main(){ 

    A B; 

    B=B.foo(); 

    //What is the value of B.a at this line of the code 
} 
+2

あなたの質問には、クラスにデストラクタがある場合、ほぼ確実にコピーコンストラクタと代入演算子も必要です。 –

+1

あなたがすることは*未定義の動作*につながるので、あなたは*何でも*期待できます。これに限定されないが、[鼻悪魔](http://catb.org/jargon/html/N/nasal-demons.html)を含む。ほとんどの場合、クラッシュするだけです。右値または左値があるかどうかは関係ありません。 –

+1

@NeilButterworthによるコメントを拡大するには、[3,5、および0のルール](http://en.cppreference.com/w/cpp/language/rule_of_three)を読んでください。 –

答えて

2

問題は、それは、あなたが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(); 
} 

が出力:

enter image description here

だから、適切なコピーコンストラクタ/代入演算子を実装する、またはそれらの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; 
} 

ただし、コピー操作のセマンティクスはどのようなものでしょうか?ポインタの所有権を移しますか?値をコピーしますか?コンパイラはこれらのクラスには答えられないので、メンバーをコピーするだけです。

+0

ご意見ありがとうございます。したがって、クラスAはコピーコンストラクタとassinment opeatorの両方を持つ必要があります。 –

+0

@GultekinYegin私はまだ普通のポインタを使用し、 'std :: unique_ptr'のようなスマートポインタを使うことを勧めません。 –

関連する問題