我有以下代码
#include <iostream>
struct mystruct
{
float x;
};
void fun(mystruct* ptr)
{
mystruct str = {10};
ptr = &str;
std::cout<<"bbq";
}
class cls
{
public:
mystruct* ptr;
void fun()
{
mystruct str = {10};
ptr = &str;
std::cout<<"bbq";
}
};
int main()
{
mystruct* ptr = new mystruct;
fun(ptr);
std::cout<<"bbq";
cls obj;
obj.fun();
std::cout<<"bbq";
}
首先,指针ptr在函数中设置为本地结构的地址。当函数返回时,本地结构会按预期被破坏。
但是在类中有一个方法与成员指针相同,但是在方法重新运行后,我仍然设置了主成员指针。方法返回后,方法局部变量是否被销毁?
答案 0 :(得分:4)
你的第一个例子是没有设置传递的指针,它正在设置指针的本地副本,因为它是按值传递的。您需要通过引用传递才能使用实际参数:
void fun(mystruct*& ptr);
函数返回后,本地变量 被销毁。但即使您在指针内部看到一个设置为局部变量的值,也不能假设局部变量不被销毁。如果在将指针分配给过期对象后随时取消引用指针,则程序将具有未定义行为。
相关:Can a local variable's memory be accessed outside its scope?
答案 1 :(得分:1)
代码很奇怪。例如,在此功能中:
void fun(mystruct* ptr)
{
mystruct str = {10}; // create a structure
ptr = &str; // make ptr point to it
std::cout<<"bbq";
}
ptr
被设置为某种东西,但它从未使用过。 ptr
正在按值传递,因此无法在此函数之外产生效果。
在这里:
class cls
{
public:
mystruct* ptr;
void fun()
{
mystruct str = {10}; // create local variable
ptr = &str; // make ptr point to it
std::cout<<"bbq";
}
};
您正在将类成员ptr
设置为指向局部变量,但是当函数返回时该变量将被销毁,因此ptr
指向垃圾。 <{1}}在你的例子中没有被再次使用,所以没有伤害,但它仍然很奇怪。
在你的主要:
ptr
在这种情况下,不删除您分配的内容没有特别的害处,因为 这是程序的结束,但最好是动态删除 一般分配对象。
答案 2 :(得分:1)
我们可以通过这样做来导致失败:
struct mystruct
{
float x;
~mystruct() { x = 99; }
};
class cls
{
public:
mystruct* ptr;
void fun()
{
mystruct str = {10};
ptr = &str;
std::cout<<"bbq";
}
void fun2()
{
std::cout << ptr->x << std::endl;
}
};
...
obj.fun();
obj.fun2();
现在,可能会发生obj.fun2();
打印99,或者它可能会显示一些随机的其他数字,或者它可能会崩溃。这是因为“使用已被销毁的对象是未定义的行为” - 未定义的行为意味着C ++标准没有定义发生的事情,并且“任何事情都可能发生”,包括崩溃或挂起,或者它“按预期工作” ”。但是物体将被摧毁。由于原始代码在它指向的对象被销毁之后实际上没有使用ptr
,所以没有任何不好的事情发生(实际上,它甚至不是示例代码中未定义的行为 - 它只是未定义为“使用指向对象”在对象被销毁之后“)。
编辑:
然而,这段代码:
mystruct* ptr = new mystruct;
fun(ptr);
std::cout<<"bbq";
导致内存泄漏,因为永远不会删除ptr
(如果fun
在函数本身之外实际修改ptr
,例如使用mystruct *&ptr
作为参数,那么你将有一个不再被引用的mystruct
的内存块,这是一个更糟糕的内存泄漏 - 当然是ptr
中指向被破坏对象的值,所以你可以'无论如何都要使用ptr