创建类的实例

Kol*_*nya 97 c++ constructor class

第1,2,3,4行有什么区别?

我什么时候使用?

为什么第3行打印constructor Foo和第7行返回错误而第8行没有?

#include <iostream>     
using namespace std;

class Foo
 {
   public:
   Foo ( )
   {
      cout << "constructor Foo\n";
   }               
};

class Bar
 {
   public:
   Bar ( Foo )
   {
      cout << "constructor Bar\n";
   }
};

int main()
{
   /* 1 */ Foo* foo1 = new Foo ();
   /* 2 */ Foo* foo2 = new Foo;
   /* 3 */ Foo foo3;
   /* 4 */ Foo foo4 = Foo::Foo();

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );
   /* 6 */ Bar* bar2 = new Bar ( *new Foo );
   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );
   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );

   return 1;
}
Run Code Online (Sandbox Code Playgroud)

Luc*_*ore 118

   /* 1 */ Foo* foo1 = new Foo ();
Run Code Online (Sandbox Code Playgroud)

Foo在动态内存中创建类型的对象.foo1指向它.通常,您不会在C++中使用原始指针,而是使用智能指针.如果Foo是POD类型,这将执行值初始化(这里不适用).

   /* 2 */ Foo* foo2 = new Foo;
Run Code Online (Sandbox Code Playgroud)

与之前相同,因为Foo不是POD类型.

   /* 3 */ Foo foo3;
Run Code Online (Sandbox Code Playgroud)

创建在自动存储中调用的Foo对象foo3.

   /* 4 */ Foo foo4 = Foo::Foo();
Run Code Online (Sandbox Code Playgroud)

使用复制初始化来创建在自动存储中Foo调用的对象foo4.

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );
Run Code Online (Sandbox Code Playgroud)

使用Bar的转换构造函数Bar在动态存储中创建类型的对象.bar1是指向它的指针.

   /* 6 */ Bar* bar2 = new Bar ( *new Foo );
Run Code Online (Sandbox Code Playgroud)

和之前一样.

   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );
Run Code Online (Sandbox Code Playgroud)

这只是无效的语法.你不能在那里声明一个变量.

   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );
Run Code Online (Sandbox Code Playgroud)

如果bar3没有在7中宣布,将按照相同的原则工作和工作到5和6 .

5和6包含内存泄漏.

类似的语法new Bar ( Foo::Foo() );不常见.通常是new Bar ( (Foo()) );-最令人烦恼的解析的额外括号帐户. (校正的)

  • 实际上,`Foo :: Foo()`甚至合法吗?我以为不是. (2认同)

Mik*_*our 18

  1. 从免费存储中分配一些动态内存,并使用其默认构造函数在该内存中创建一个对象.你永远不会删除它,所以内存泄露.
  2. 与1完全相同; 在用户定义类型的情况下,括号是可选的.
  3. 分配一些自动内存,并使用其默认构造函数在该内存中创建一个对象.当对象超出范围时,内存将自动释放.
  4. 类似于3.在理论上,命名对象foo4通过默认构造,复制和销毁临时对象来初始化; 通常,这被省略,给出与3相同的结果.
  5. 分配动态对象,然后通过复制第一个来初始化第二个.两个物体都泄露了; 并且没有办法删除第一个,因为你没有保留指针.
  6. 与5完全相同.
  7. 不编译.Foo foo5是宣言,而不是表达; function(和constructor)参数必须是表达式.
  8. 创建临时对象,并通过复制它来初始化动态对象.只有动态对象泄露; 临时表在完整表达式结束时自动销毁.请注意,您可以使用Foo()而不是等效Foo::Foo()(或确实Foo::Foo::Foo::Foo::Foo())创建临时

我什么时候使用?

  1. 不要,除非你喜欢你的代码上不必要的装饰.
  2. 如果要创建比当前范围更长的对象.记得在完成后删除它,并学习如何使用智能指针更方便地控制生命周期.
  3. 如果需要仅存在于当前范围内的对象.
  4. 不要,除非你认为3看起来很无聊以及添加一些不必要的装饰.
  5. 不要,因为它泄漏了记忆,没有恢复的机会.
  6. 不要,因为它泄漏了记忆,没有恢复的机会.
  7. 不要,因为它不会编译
  8. 当您想要Bar从临时创建动态时Foo.

  • @Kolyunya:是的,你可以而且应该.但是你没有在你的示例代码中这样做,我虽然值得指出. (2认同)

Cod*_*ash 5

第1,2,3,4行将调用默认构造函数。它们本质上是不同的,因为1,2是动态创建的对象,而3,4是静态创建的对象。

在第7行中,您可以在参数调用内创建一个对象。因此,这是一个错误。

第5行和第6行是内存泄漏的邀请。