前几天,当我意识到我没有为我的功能释放内存时,我正要问一个相当简单的初学者问题我正在研究的c ++函数。这似乎永远不会在这里结束。
这似乎是一个常见的问题,但我无法在c ++的理解水平上找到任何东西
如何在此代码中正确释放内存
#include <iostream>
class thing{
public:
int a;
};
thing makeThing(){
thing *t = new thing;
t -> a = 5;
return *t;
}
int main(){
thing thing1 = makeThing();
std::cout << "a: " << thing1.a << std::endl;
return 0;
}
据我所知,在函数终止后我无法释放它。 我试过这个:
delete &thing1;
但是基于核心转储,我认为不是这样做的。
答案 0 :(得分:3)
有时,释放内存的最简单方法是不要将其分配给:
thing makeThing(){
thing t;
t.a = 5;
return t;
}
您尝试做的事情不起作用的原因是,当您有:
delete &thing1;
这是您本地对象的地址......这不是您实际分配的地址。那个被复制到你的,现在你无法访问它。
如果您想分配thing
,则需要直接返回指针。最好以某种方式包裹:
std::unique_ptr<thing> makeThing() {
std::unique_ptr<thing> t(new thing);
t->a = 5;
return t;
}
答案 1 :(得分:3)
由于您按值返回,这意味着您将返回该对象的副本。在new things
创建的原始对象在函数返回后无法到达(无论如何都不可靠)。
你可以返回一个指针:
thing* makeThing(){
thing *t = new thing;
t -> a = 5;
return t;
}
删除它。
但是你应该真的只返回一个对象,在这种情况下甚至不用new
分配任何东西。
答案 2 :(得分:1)
thing makeThing(){
thing *t = new thing;
t -> a = 5;
return *t;
}
导致即时内存泄漏。 t
返回后,makeThing()
变量将超出范围,并且永远不会释放分配的内存,也无法使用适当的delete
语句进行发布。
有新创建的t
返回的副本。
要修复它,只需创建一个局部变量并重新复制:
thing makeThing(){
thing t;
t.a = 5;
return t;
}
答案 3 :(得分:0)
如果您真的想使用new
,这是正确的方法。此代码是C ++ 11,因此您可能需要打开某个选项,如果它不是您正在使用的编译器中的默认选项。我习惯使用C ++ 11,因为该语言版本的改进确实值得。
#include <iostream>
#include <memory>
#include <ostream>
class thing {
public:
int a;
};
std::ostream& operator<<(std::ostream& os, const thing& t) {
os << t.a;
return os;
}
std::unique_ptr<thing> makeThing() {
std::unique_ptr<thing> t(new thing);
t->a = 5;
return std::move(t);
}
int main() {
auto thing1 = makeThing();
std::cout << "a: " << *thing1 << std::endl;
return 0;
}
但实际上,如果你想要做的就是创建一个对象,就不需要在堆上分配它。你可以像下面的代码那样做。请注意,该对象是在不使用new
的情况下创建的。从makeThing()返回时复制该对象,并且编译器在执行此操作时使用class thing
的默认复制构造函数(我没有替换)。
#include <iostream>
#include <ostream>
thing makeThing() {
thing t;
t.a = 5;
return t;
}
int main() {
auto thing1 = makeThing();
std::cout << "a: " << thing1 << std::endl;
return 0;
}
ostream插入器不需要更改,所以我省略了它。类定义也一样。