Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.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++;动态内存细节_C++_Memory_Memory Management_Dynamic_Free - Fatal编程技术网

C++ C++;动态内存细节

C++ C++;动态内存细节,c++,memory,memory-management,dynamic,free,C++,Memory,Memory Management,Dynamic,Free,我是一名C和Java程序员,所以内存分配和OOP对我来说并不是什么新鲜事。但是,我不确定如何用C++实现对象来避免内存泄漏。即: string s1("0123456789"); string s2 = s1.substr(0,3); s2现在有一个新的字符串对象,因此必须通过以下方式释放它: delete &s2; 对吧? 此外,我是否正确地假设我必须删除函数返回的任何(新)对象的地址,而不管返回类型不是指针或引用?当必须释放堆上的对象时,它不会作为指针返回,这似乎很奇怪。否 超出

我是一名C和Java程序员,所以内存分配和OOP对我来说并不是什么新鲜事。但是,我不确定如何用C++实现对象来避免内存泄漏。即:

string s1("0123456789");
string s2 = s1.substr(0,3);
s2
现在有一个新的字符串对象,因此必须通过以下方式释放它:

delete &s2;
对吧?

此外,我是否正确地假设我必须删除函数返回的任何(新)对象的地址,而不管返回类型不是指针或引用?当必须释放堆上的对象时,它不会作为指针返回,这似乎很奇怪。

超出范围时,
s1
s2
都将被破坏


s1.substr()
将创建一个您不必考虑的临时对象。

为什么您必须手动释放s2?
s2中动态内存的删除将由std::string析构函数处理。

否,
s2
无需手动删除。它是堆栈上的一个局部变量,一旦超出范围就会自动销毁,就像声明时自动分配的一样。通常,您只删除分配给
new
内容

函数返回的临时对象将自动管理,并在语句结束时销毁-如果需要更长时间,通常会在销毁临时对象之前将其复制到局部变量(例如,通过简单的赋值,如
Object o=f();
或类似于
substr()的行)
在您的示例中调用)


如果函数返回指针,则指向的对象不会像这样自动管理。在文档中,应注明所有工作完成后,谁负责删除对象。作为默认约定,通常分配对象的人负责再次删除该对象,但需要在某处记录详细信息。

s1和s2都是自动分配的。你不能删除这些。 您只能
删除使用
new
创建的
对象

C++知道三种分配模式:自动、静态和动态。仔细阅读这些。 自动值,如示例中的字符串,在它们离开作用域时会自动释放。它们的析构函数被自动调用。调用字符串析构函数时,将释放操作期间动态分配的字符串的任何内存。


您只需释放分配的内存(即通过new或memalloc)。

正如其他人所说,此处无需删除。除非您看到一个
新的
,否则您(通常)不需要
删除
。我确实想添加
s2
没有新的字符串对象
s2
是从声明时起的字符串对象。将
s1
的片段分配给
s2
会修改
s2
,使其包含与子字符串中相同的字符


理解这里发生的事情非常重要,你深入挖掘C++会变得更加重要。哦,恭喜学习一种新的语言。

< P>现代C++中最重要的概念之一(尤其是来自C背景)是。C++封装了类中的资源(如内存(或互斥或事务)”,这些类在“构造”中获取资源(字符串构造函数分配动态内存)并在销毁时“释放”它(字符串类的释放使其释放)。由于堆栈对象的销毁是确定性的(基于堆栈的对象在封闭的作用域失效时失效),因此不必编写发布,即使抛出异常也会发生


所以,没有。在我的大多数编码中,我从来没有写过一个显式删除(或delete[]),因为资源是由字符串、STL conatiner或共享或范围化的ptr管理的。

答案有两层

首先,变量可以用几种不同的方式声明:

  • 作为局部变量(函数内部或类成员)。示例:
    inti
    ,或
    inti=42
    。它们具有自动存储持续时间(这些示例在技术上是
    auto int i
    auto int i=42
    的简写,但实际上从未使用过
    auto
    关键字。这意味着这些变量在超出范围时将自动释放。它们的析构函数保证被调用(无论您如何离开作用域,无论是通过函数返回还是通过引发异常,它们的析构函数都将在超出作用域时被调用,然后释放它们使用的内存)。这样声明的局部变量将在堆栈上分配
  • 静态变量(带有
    static
    关键字,意味着静态存储持续时间,与上面显示的自动相反。这些变量在程序持续时间内保持不变,因此不必被释放
  • 在堆上,使用动态分配(
    new int
    new int(42)
    )。必须通过调用
    delete
    手动释放它们
因此,在最低级别上,您基本上只需要保持对称性。如果某个东西是通过
new
分配的,则通过
delete将其释放,
malloc
通过
free
释放,通过
delete[]将其释放`.和声明的变量(没有任何这些变量)将自动处理,不应手动释放

现在,为了保持内存管理的简单性,通常使用这种技术。这种技术基于这样一种观察:只有动态分配的对象才需要手动释放,而局部变量为您提供了一个非常方便的钩子,用于在局部变量超出范围时实现自定义操作

因此,动态分配被封装在一个单独的类中,该类可以作为堆栈上的本地对象进行分配