我对c ++中的范围和内存管理存有疑问。这是我遇到麻烦的情况:
Abc function f()
{
Abc c;
return c;
}
Abc d = f();
if(d) cout << "hi";
它会说“嗨”吗?我的意思是...在f()中创建的Abc不是动态的(我们没有写新的)...但是我们返回值,所以我们保留对该对象的引用。它是否有价值,或者一旦它超出其范围就会死亡?
谢谢!
答案 0 :(得分:1)
在你的情况下,在下面的第二种情况下,不可能做出确切的陈述:
Abc* function f()
{
Abc *c = new Abc();;
return c;
}
Abc* d = f();
if(d) cout << "hi";
是的,它会说“hi”,不同之处在于,在第一种情况下,c保留在Stack中,而在第二种情况下,它保存在堆中。在您的情况下,键入if(d)不是检查对象是否存活的好方法,因为它是在堆栈上定义的。
为了检查你的情况,你可以在Abc的析构函数中添加一个日志,看看它是否会被命中。您将观察到当使用f()返回对象时,将调用Abc的析构函数。但这并不意味着物体已经死亡。只调用它的析构函数。但在这种情况下,您无法正确使用析构函数。这是选择指向对象的指针而不是直接定义它们的原因之一。
答案 1 :(得分: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)一起编译。
答案 2 :(得分:0)
Abc f()
{
Abc c;
return c;
}
创建c
类型的Abc
,复制它并从函数返回(可以省略NRVO
副本。)
Abc d = f();
if(d) cout << "hi";
创建d
并使用函数f
的返回值对其进行复制初始化。什么是Abc
类型?如果它有operator bool
(或operator T()
其中T
可隐式转换为bool
) - 可能会打印“hi”。