我正在以两种略有不同的方式创建一个c++
对象,在以下代码中,当CASE
为0
时,存在内存泄漏,但是{{1 }}。
else
当我设置#include <string>
#define CASE 1
class A {
private:
std::string *s;
public:
A(std::string *p_s) { s = p_s; }
};
int main() {
#if CASE==0
auto a = A(new std::string("Hello"));
#else
auto s = std::string("Hello");
auto a = A(&s);
#endif
}
时,CASE 0
说存在内存泄漏
valgrind
在其他情况下(即valgrind ./a.out
==24351== Memcheck, a memory error detector
==24351== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==24351== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==24351== Command: ./a.out
==24351==
==24351==
==24351== HEAP SUMMARY:
==24351== in use at exit: 32 bytes in 1 blocks
==24351== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated
==24351==
==24351== LEAK SUMMARY:
==24351== definitely lost: 32 bytes in 1 blocks
==24351== indirectly lost: 0 bytes in 0 blocks
==24351== possibly lost: 0 bytes in 0 blocks
==24351== still reachable: 0 bytes in 0 blocks
==24351== suppressed: 0 bytes in 0 blocks
==24351== Rerun with --leak-check=full to see details of leaked memory
==24351==
==24351== For counts of detected and suppressed errors, rerun with: -v
==24351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
),它按预期工作,并且valgrind不报告任何内存泄漏。
无论哪种情况,我都无法理解我正在传递指针,也没有显式地释放内存,那么为什么它们的行为有所不同?
答案 0 :(得分:5)
此行为的原因是您的类A
并非旨在获取传递给它的std::string*
的所有权:其std::string *s
成员假定该对象是要传递的指针进入构造函数将在外部被破坏。
当对象没有被破坏时,这会导致内存泄漏:delete
永远不会在传递给构造函数的new string
上调用,从而导致内存泄漏。
在第二种情况下,指针指向自动存储中的字符串。 main
结束时它会被销毁,从而防止内存泄漏。
答案 1 :(得分:4)
因为有指针,所以不会发生内存泄漏。
内存泄漏是因为您new
想要但没有delete
。
获取指向自动存储变量的指针不会阻止该变量被自动清除。
实际上,在这种情况下尝试delete &a
是错误/破碎/邪恶/非法/异端。
答案 2 :(得分:1)
这与以下内容没有什么不同:
// first case, leak
int *j = new int (5);
//
// second case, no leak
int q = 5;
int *j = &q;
在第一种情况下,我们使用new
分配了内存,完成后delete
是我们的责任。在第二种情况下,我们在堆栈上创建q
,并在超出范围时将其销毁。
答案 3 :(得分:1)
CASE == 0
auto a = A(new std::string("Hello"));
这意味着您正在new
-正在堆中的对象->您必须明确 delete
它-您不在代码段中->内存泄漏
其他
auto s = std::string("Hello");
auto a = A(&s);
auto s = std::string("Hello");
:这意味着您正在堆栈中创建对象,并且auto a = A(&s);
:获取地址(当然是在堆栈中)。->没有内存泄漏。