Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这种新的使用是否会造成内存泄漏?_C++ - Fatal编程技术网

C++ 这种新的使用是否会造成内存泄漏?

C++ 这种新的使用是否会造成内存泄漏?,c++,C++,我今天看到了一个我不熟悉的new用法 { string * test = new string("bye"); new (test) string("hello"); cout << *test << endl; //prints "hello" delete test; } 这里发生了什么事?您正在查看的内容称为新位置。它在已经分配的内存块上调用构造函数 由于原始对象从未被破坏,它肯定会导致内存泄漏。如果没有,可能是因为短字符串包含在

我今天看到了一个我不熟悉的
new
用法

{
    string * test = new string("bye");
    new (test) string("hello");
    cout << *test << endl; //prints "hello"

    delete test;
}

这里发生了什么事?

您正在查看的内容称为新位置。它在已经分配的内存块上调用构造函数

由于原始对象从未被破坏,它肯定会导致内存泄漏。如果没有,可能是因为短字符串包含在对象本身中,不会导致字符串缓冲区的分配。

是的,您有(*可能)内存泄漏。不,检查代码不会显示其他内容。它演示了您拥有的两个指针都指向同一个对象


要理解这一点,请注意,
std::string
通常将文本存储在其他地方,并动态分配缓冲区

因此,当您
new
a
std::string
时,至少有两种动态分配:

  • 动态分配
    std::string
    对象本身
  • 该对象的字符串缓冲区的动态分配
内存泄漏与缓冲区有关,缓冲区未释放,因为第一个
std::string
对象的析构函数未运行



*)“可能”而不是“确定”,因为与
std::vector
相反,std::string可能会采用短缓冲区优化,直接存储数据。

确实存在潜在内存泄漏,但不是因为您可能会想,有两个
new
s,只有一个
delete
。那其实很好

问题是第一个字符串的析构函数永远不会运行。分配给它的任何内部内存都不会被释放

为了解释,第二个
new
是所谓的放置
new
。这是一种在已经分配的内存上调用构造函数的方法。(这是一个过于简单化的问题,但我们不要偏离正题。如果你想了解更多关于位置的信息,你知道谷歌在哪里。
new
new(test)string(“hello”)
的效果是它用另一个字符串(
“hello”
)覆盖了第一个字符串(
“bye”
)。放置
new
不会分配更多内存。它只是在现有内存区域上运行
string::string(const char*)
构造函数


这就是为什么程序会打印两次
hello
test
test2
都指向同一个字符串,因此当您覆盖该字符串时,更改将显示在两个变量中。变量本身没有改变,但它们所指向的对象已经改变。

我不确定您想用第二个示例演示什么。为什么
coutPlacement不新建,是的,它会泄漏,因为原始对象的析构函数没有运行。@megar,因为我已将
test2
分配给
test
的原始值。如果第二个
new
语句分配了新内存,则
test
的值应该更改。但事实并非如此。鉴于这段代码,我唯一看到的是在放置之前手动触发析构函数;使用placement new(奇怪的是,下面的答案都没有提到)时,有一些东西是有保证的。@WhozCraig那么,如果我添加了
test->~string()在我的新位置之前,是否没有可能的内存泄漏?另外,这是否意味着任何带有一个小析构函数的东西都可以用一个新的位置构造而不用担心呢?吹毛求疵:如果有一个超负荷的
操作符new
接受一个
std::string*
,那么就不一定返回那个指针。说明了提供不完整代码的危险性(正如OP所做的),以及教授细节的危险性(OP以后可能会遇到区分重要的代码)。是的,你完全正确。我写了一张便条,说我的答案出于教学目的过于简单化了。
string * test = new string("bye");
string * test2 = test;
new (test) string("hello");
cout << *test << endl; //prints "hello"
cout << *test2 << endl; //also prints "hello"