我所知道,返回对局部变量的引用与返回指向局部变量的指针相同,这会导致C ++中的内存泄漏。
但这是否适用于数据成员?
代码:
class MyClass
{
public:
std::string& getId();
private:
std::string id;
};
MyClass std::string& getId()
{
return id;
}
int main()
{
MyClass* c = new MyClass;
std::string brokenRef = c->getId();
// or may be std::string& brokenRef = c->getId();
delete c;
cout << brokenRef << endl; // <<< this should be a ref to unknown location, correct?
}
感谢。
答案 0 :(得分:1)
是的,它适用。即使您的MyClass实例不是严格本地的main,但在引用之前动态分配和释放。但是有相同的效果。
现有代码是正确的,因为您在有效时复制字符串。已注释掉的参考版本确实是一个破损的参考。
答案 1 :(得分:1)
排队
std::string brokenRef = c->getId();
您创建一个新的字符串实例,并使用由getId()返回的引用引用的字符串初始化它。从brokenRef
开始,MyClass
生命完全独立于brokenRef
对象。因此,MyClass
愉快地过时了std::string& brokenRef = c->getId();
被摧毁的对象。
您可以通过分配对引用变量的引用来实现所需的效果:
{{1}}
除此之外,我认为你混合术语内存泄漏和悬空指针(悬空引用)。返回指针或成员的引用不会导致内存泄漏。但是在对象被销毁之后使用它们(解除引用)(因为存储成员以前存储的内存被释放并且它们变得悬空)会导致未定义的行为并且很可能会崩溃。
答案 2 :(得分:0)
您的示例中没有问题,因为您已分配到string
,如果您将其转为string&
,那么只要delete c
它就会无效。
(并不会导致内存泄漏)。
答案 3 :(得分:0)
只要您的MyClass未被删除,参考就有效。
或者如果您将它声明为堆栈变量,那么只要它在范围内,类实例中的成员就是有效的。
答案 4 :(得分:0)
你会得到一些值,但它会是一些随机值,因为包含它的对象已被破坏。
理想情况下,我会删除并将其设置为null
所以在你的...
c=null;
面向对象的C ++与每个基于OO的语言具有相同的对象生存期限制
对象的生命周期在创建时开始,在被销毁时结束。在C ++类定义中,具有相同名称作为类的成员函数是构造函数。这是一个在创建类的实例时自动调用的函数。构造函数通常用于将对象的数据成员初始化为其默认状态,但也可用于分配资源(内存,文件等)。对于任何类,可以声明许多构造函数,每个函数使用不同类型的参数,提供不同的初始化实例的方法。类的默认构造函数是可以在没有任何参数的情况下调用的类的构造函数。如果没有为该类明确声明构造函数,则将自动生成类的默认构造函数。类的复制构造函数是一个构造函数,可以调用它来复制该类的对象(它具有相应类型的单个参数)。例如,当一个参数对象通过值传递给一个函数,或者一个对象用另一个对象的值初始化时,就会调用一个复制构造函数。如果没有为该类显式声明复制构造函数,则将自动生成类的copy构造函数。具有相同名称作为具有前导波形符(〜)的类的成员函数是析构函数。这是在删除对象时自动调用的函数。析构函数通常用于释放为对象分配的任何内存(也可能释放在施工期间获得的任何其他资源。。类定义中不需要构造函数和析构函数。
有几种方法可以在C ++程序中创建对象。一种是将变量定义为特定类,作为全局变量或块内的局部变量。在程序执行期间遇到声明时,将为该对象分配空间,并调用该对象的构造函数(如果有)。类似地,当对象变量超出范围时,会自动调用其析构函数。创建对象的另一种方法是声明一个变量,该变量是指向对象类的指针,并调用C ++ new运算符,该运算符将为对象分配空间并为对象调用构造函数(如果有)。在这种情况下,指针变量必须使用delete运算符显式释放。调用new时执行对象的构造函数,并在调用delete时执行析构函数。也可以通过在表达式中显式使用构造函数来构造对象。
当一个类派生自另一个类时,它继承了它的父类'constructor和析构函数。父构造函数在derivedconstructors之前调用。析构函数以相反的方向调用,从派生类向上通过其父链。