2017-02-25 290 views
0

对于B.a之后的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的评论,你应该阅读[三,五和零的规则](http://en.cppreference.com/w/cpp/language/rule_of_three)。 –

回答

2

的问题是,你有没有为A和自分配B至少调用赋值运算符(在这种情况下,默认的,由编译器生成)定义的拷贝构造函数/赋值运算符,它只需从返回的“A”实例中复制a指针,然后当该实例被删除时,内存被释放,B中的a成员现在指向垃圾。如果你加点记录不难看出:

#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

因此,要么实现适当的拷贝构造函数/赋值运算符,或使他们的一个/两个删在使用原始指针时转义拷贝。例如,添加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类需要复制构造函数和assginment操作符。 –

+0

@GultekinYegin我仍然建议不要使用普通指针并使用智能指针,比如'std :: unique_ptr'。 –

相关问题