2013-04-11 204 views
0

我对C++中的范围和内存管理有疑问。这是我遇到麻烦的情况:内存和范围管理

Abc function f() 
{ 
    Abc c; 
    return c; 
} 

Abc d = f(); 
if(d) cout << "hi"; 

会说“hi”吗?我的意思是...在f()中创建的Abc不是动态的(我们没有写一个新的)......但是我们正在返回值,所以我们获得了对该对象的引用。它会有价值吗?或者一旦它脱离了它的范围,它就会死亡?

谢谢!

+1

你为什么不自己尝试看看?如果在这里撰写和发布问题,这会花费更少的时间。 – 2013-04-11 08:55:19

+0

另外,“我们正在返回值” - 是的,“所以我们保留对对象的引用” - false。我在这里没有看到参考。 – 2013-04-11 08:56:21

+1

只有在'Abc'可以转换为'bool'或者可以转换为bool的内建类型时才会编译。是这样吗? – juanchopanza 2013-04-11 08:58:06

回答

1
#include <iostream> 
using std::cout; 
using std::endl; 

class Abc 
{ 
    int m_value = 0; 
public: 
    Abc() 
    { 
     cout << "Default Constructor" << std::endl; 
    } 

    Abc(const Abc& _source) 
    { 
     cout << "Copy Constructor" << std::endl; 
     //copy stuff 
    } 

    Abc& operator=(const Abc& _source) 
    { 
     cout << "assignment operator" << std::endl; 
     if (this == &_source) 
      return *this; 
     //copy stuff 

     return *this; 
    } 

    Abc(const Abc&& _source) 
    { 
     cout << "Move Constructor" << std::endl; 
     //move stuff 
    } 

    Abc& operator=(const Abc&& _source) 
    { 
     cout << "move assignment operator" << std::endl; 
     //move stuff 
     return *this; 
    } 

    ~Abc() 
    { 
     cout << "Destructor"<< std::endl; 
    } 

    void setValue(int _value) 
    { 
     m_value = _value; 
    } 

    int getValue() 
    { 
     return m_value; 
    } 
}; 

Abc f() 
{ 
    Abc c; 
    c.setValue(100); 
    cout << "c value: " << c.getValue() << endl; 
    return c; 
} 

int main() 
{ 
    Abc d = f(); 
    cout << "d value: " << d.getValue() << endl; 
    d.setValue(200); 
    cout << "d value: " << d.getValue() << endl; 
} 

这里是输出:

默认构造

C值:100

d值:100

d值:200

析构

从这里你可以看到,编译器足够聪明地重用分配的对象而不用做任何愚蠢的副本(C++ 98/03,C++ 11相同的输出)。

编译MinGW(GCC 4.7.1)。

0
Abc f() 
{ 
    Abc c; 
    return c; 
} 

创建Abc类型的c,复制和从函数返回(带NRVO拷贝可以被消隐)。

Abc d = f(); 
if(d) cout << "hi"; 

创建d与功能f返回的值复制初始化。什么是Abc类型?如果它有operator bool(或operator T(),其中T可以隐式转换为bool) - 可能会打印“嗨”。

1

你的情况是不可能作出确切的声明,在下面的第二种情况:

Abc* function f() 
{ 
    Abc *c = new Abc();; 
    return c; 
} 

Abc* d = f(); 
if(d) cout << "hi"; 

是的,它会说“你好”,所不同的是,在第一种情况下,c是保存在堆栈中,而在第二种情况下保存在堆栈中。在你的情况下,键入if(d)不是一个很好的方法来检查对象是否存在,因为它是在栈中定义的。

为了检查你的情况,你可以添加一个日志到Abc的析构函数,看它是否会被击中。当你用f()返回对象时,你会观察到Abc的析构函数被调用。但这并不意味着物体已经死亡。只有它的析构函数被调用。但在这种情况下,你不能正确使用析构函数。这是选择指向对象的指针的原因之一,而不是直接定义它们的原因之一。