处理类new和delete运算符C+中的内存泄漏+; 我喜欢在C++中使用运算符新< /C> >和 Dele> ,但是程序代码中经常会出现调用删除>代码>问题。

处理类new和delete运算符C+中的内存泄漏+; 我喜欢在C++中使用运算符新< /C> >和 Dele> ,但是程序代码中经常会出现调用删除>代码>问题。,c++,memory-management,memory-leaks,C++,Memory Management,Memory Leaks,例如,在以下代码中: class Foo { public: string *ace; Foo(); ~Foo(); }; Foo::Foo() { ace = new string; } Foo::~Foo() { delete ace; } void UI::ButtonPressed() { //Happens when an event is triggered Foo *foo = new Foo; ui->label =

例如,在以下代码中:

class Foo {
public:
    string *ace;
    Foo();
    ~Foo();
};
Foo::Foo() {
    ace = new string;
}
Foo::~Foo() {
    delete ace;
}
void UI::ButtonPressed() { //Happens when an event is triggered
    Foo *foo = new Foo;
    ui->label = ace; //Set some text on the GUI
    delete foo; //Calls the destructor, deleting "ace" and removing it from the GUI window
}
我可以声明一个
new
字符串,但当我
delete
它时,它会从GUI表单中删除该值,因为该字符串现在已被删除

有没有办法让我以后删除这个分配的字符串

我不想将它声明为全局变量,然后在程序源代码的最后一行删除它。我永远不能调用
delete
,但从我所学的内容来看,这是不好的,会导致内存泄漏。

您应该阅读有关删除的内容。对于C++程序员来说,它是最重要的概念之一。 其基本思想是,资源(新对象、HTTP连接等)的生命周期与对象的生命周期相关联。这是编写异常安全代码所必需的


在您的情况下,UI小部件将创建对象的副本,并在其自己的析构函数中释放它。调用代码可以立即释放它的副本(在另一个析构函数中)。

如果对
ace
ui->label
都使用
std::string
,那么一旦
foo
对象超出范围,就不必担心
ace
的内存被
delete
d

右侧参数的副本可用于
=
(赋值操作)上的
ui->label
。你可以在C++上更多地阅读它。


此外,可以通过使用智能指针(例如由提供的指针)完全避免此类问题。在StAcExtRoad上阅读这个主题,以获得更好的理解。

< P>这里有一个更为通用的C++程序:

class Foo {
public:
    std::string ace;

    Foo() : ace() {
      // nothing to do here. ace knows how to create itself…
    }

    // and copy itself…
    Foo(const Foo& other) : ace(other.ace) {}

     // and clean up after itself…
    ~Foo() {
    }

    // and copy/assign itself…
    Foo& operator=(const Foo& other) {
      this->ace = other.ace;
      return *this;
    }
};


void UI::ButtonPressed() {
  // `new` is not needed here, either!
  Foo foo;
  ui->label = foo.ace; //Set some text on the GUI
  // `delete` is not needed here
}

如果你真的需要调用<代码>新< /C>,总是使用一个适当的智能指针——写<代码>删除< /C> >被从现代C++中删除] 好吧,关于你的代码有很多话要说。有些事情已经说过了,例如,你应该把字符串变成一个普通成员,这样分配/去配置问题完全消失了(这是C++程序的一般规则:如果你不需要使用动态分配,那么不要,周期)。此外,使用适当的智能指针可以为您进行内存管理(这也是C++中的一条一般规则:除非您真的必须,否则不要自己管理动态分配)

但是,让我们假设您必须使用动态分配,并且您必须在此处使用原始指针和直接
new
delete
。另一个重要的规则进来了(实际上它不是C++特定规则,而是一个通用的OO规则):不要让成员公开。将其设置为私有成员,并提供用于设置它的公共成员函数。然后,该公共成员函数可以在将指针指定给新对象之前正确删除旧对象。请注意,一旦指定了指针,除非已将旧值存储在其他位置,否则旧值将永远丢失,如果在此之前尚未删除对象,则以后无法删除它

您还想考虑将指针传递给对象的所有权是否是一个好主意(并且分配给析构函数中的删除的指针成员是一种不太明显的传递所有权的方式)。这使对象生存期管理复杂化,因为您必须记住是否已将某个对象传递给所有权声明对象(但如果您有始终传递给所有权声明对象的严格策略,则这不是问题)。像往常一样,智能指针在这方面可能会有所帮助;但是,您可以考虑复制对象是否是一个更好的选择(对于<代码> STD::String ),这是肯定的,但在这里,最好还是有一个直接成员,如上所述。 因此,这里有一个完整的规则列表,其中较早的规则优先于较晚的规则,除非有充分的理由不使用它:

  • 不要使用动态分配
  • 使用智能指针管理动态分配
  • 仅在构造函数中使用
    new
    ,仅在相应的析构函数中使用
    delete
  • 对于同一类的成员函数中的特定指针,始终使用
    new
    delete
    。(事实上,前一条规则是这条规则的特例,但这是一个特例,应该优先于一般规则。)

  • std::string
    可以变化,因此在您的示例中可以声明
    std::string ace你应该了解更多关于智能指针的知识。等等,你知道智能指针是否与非标准C++数据类型一起工作,比如“代码> QStult<代码> >(Qt)和其他?Qt也有某种智能指针,是的,
    std::smart_ptr
    等应与Qt…@user99545配合使用:
    std::string
    存在的原因之一是,您不必担心
    new
    ing和
    delete
    ing字符数组。只要让它成为一个类成员,它就会自行处理。·正如@Insilico所说,
    std::string
    是一种解决方案
    std::string
    让您可以自行决定是否复制或共享数据:您不知道数据的用途,也不需要知道(从功能上讲,它就像是复制的一样)。要实现自我复制,您需要仔细阅读“三法则”,以便正确销毁。要实现自己的共享,请使用
    std::shared\u ptr
    。不幸的是,标准库中没有复制智能指针,我想即使在Boost中也没有。干杯,谢谢你教我RAII模式,经过一些快速的研究,我所有的问题都得到了回答。