我对C++中的范围和内存管理有疑问。这是我遇到麻烦的情况:内存和范围管理
Abc function f()
{
Abc c;
return c;
}
Abc d = f();
if(d) cout << "hi";
会说“hi”吗?我的意思是...在f()中创建的Abc不是动态的(我们没有写一个新的)......但是我们正在返回值,所以我们获得了对该对象的引用。它会有价值吗?或者一旦它脱离了它的范围,它就会死亡?
谢谢!
我对C++中的范围和内存管理有疑问。这是我遇到麻烦的情况:内存和范围管理
Abc function f()
{
Abc c;
return c;
}
Abc d = f();
if(d) cout << "hi";
会说“hi”吗?我的意思是...在f()中创建的Abc不是动态的(我们没有写一个新的)......但是我们正在返回值,所以我们获得了对该对象的引用。它会有价值吗?或者一旦它脱离了它的范围,它就会死亡?
谢谢!
#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)。
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
) - 可能会打印“嗨”。
你的情况是不可能作出确切的声明,在下面的第二种情况:
Abc* function f()
{
Abc *c = new Abc();;
return c;
}
Abc* d = f();
if(d) cout << "hi";
是的,它会说“你好”,所不同的是,在第一种情况下,c是保存在堆栈中,而在第二种情况下保存在堆栈中。在你的情况下,键入if(d)不是一个很好的方法来检查对象是否存在,因为它是在栈中定义的。
为了检查你的情况,你可以添加一个日志到Abc的析构函数,看它是否会被击中。当你用f()返回对象时,你会观察到Abc的析构函数被调用。但这并不意味着物体已经死亡。只有它的析构函数被调用。但在这种情况下,你不能正确使用析构函数。这是选择指向对象的指针的原因之一,而不是直接定义它们的原因之一。
你为什么不自己尝试看看?如果在这里撰写和发布问题,这会花费更少的时间。 – 2013-04-11 08:55:19
另外,“我们正在返回值” - 是的,“所以我们保留对对象的引用” - false。我在这里没有看到参考。 – 2013-04-11 08:56:21
只有在'Abc'可以转换为'bool'或者可以转换为bool的内建类型时才会编译。是这样吗? – juanchopanza 2013-04-11 08:58:06