C++:实例化类成员时使用 new 关键字与不使用 new 关键字之间的区别?

Joe*_*oey 3 c++ memory-leaks memory-management new-operator

对于编程作业,我们得到一个模板类,其中两个成员不是声明为指针,而是声明为实际对象:

Foo member;
Run Code Online (Sandbox Code Playgroud)

在构造函数中,我member = *(new Foo());最初尝试过,但了解到,至少有时,它正在复制新的 Foo 对象,因此导致内存泄漏。

我终于发现了member = Foo(),然后查了一下有什么区别。我了解到成员将在堆栈而不是堆上分配,并且一旦超出范围就会被删除。那么这对于对象来说是如何工作的呢?

成员是否仅在父/类对象被删除时才被删除?

我还有一个关于 的问题member = *(new Foo());。我正在初始化两个相同类型的成员变量:

// Members
Foo member1;
Foo member2;

// Constructor {
    member1 = *(new Foo());
    member2 = *(new Foo());
}
Run Code Online (Sandbox Code Playgroud)

由于某种原因,它似乎member1没有被复制,并且保留了与初始地址相同的地址Foo(即删除时没有内存泄漏)。member2然而,将被复制并具有不同的地址,并且内存被泄漏。对此有解释吗?

Mic*_*yan 5

你的分析不正确。这两个都是内存泄漏。您正在做的是分配对象的新副本,将值分配给成员,然后丢弃指向已分配内存的指针而不释放该内存。这两种情况都是内存泄漏。

现在,考虑以下代码:

class MemberType {
  public:
    MemberType() { std::cout << "Default constructor" << std::endl; }
    MemberType(int) { std::cout << "Int constructor" << std::endl; }
};

class Example1 {
  public:
     Example1() {}
  private:
     MemberType member_;
};

class Example2 {
  public:
      Example2() : member_(5) {}
  private:
      MemberType member_;
};

int main(int argc, char** argv) {
   Example1 example1;
   Example2 example2;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码将打印两种不同类型的构造函数。请注意,以默认方式初始化成员根本不需要任何初始化代码。因此,在默认初始化情况下,您的 new 语句(甚至没有 new 的赋值)将是不必要的。使用默认构造函数以外的构造函数初始化成员时,正确的方法是使用初始值设定项列表。(初始化列表是示例中“:member_(5)”所发生的情况。

有关在C++ 中构造对象的更多信息,请参阅有关构造函数的 C++ 常见问题解答。