创建类的实例

时间:2012-09-03 13:18:57

标签: c++ class constructor

第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;
}

3 个答案:

答案 0 :(得分:108)

   /* 1 */ Foo* foo1 = new Foo ();

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

   /* 2 */ Foo* foo2 = new Foo;

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

   /* 3 */ Foo foo3;

在自动存储中创建一个名为Foo的{​​{1}}对象。

foo3

使用复制初始化在自动存储中创建名为 /* 4 */ Foo foo4 = Foo::Foo(); 的{​​{1}}对象。

Foo

使用foo4的转换构造函数在动态存储中创建 /* 5 */ Bar* bar1 = new Bar ( *new Foo() ); 类型的对象。 Bar是指向它的指针。

Bar

与以前相同。

bar1

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

   /* 6 */ Bar* bar2 = new Bar ( *new Foo );

如果7中没有宣布 /* 7 */ Bar* bar3 = new Bar ( Foo foo5 ); ,那么按照相同的原则工作和工作到5和6。

5&amp; 6 包含内存泄漏。

/* 8 */ Bar* bar3 = new Bar ( Foo::Foo() ); 这样的语法并不常见。它通常是bar3 - 额外的括号帐户,用于最烦恼的解析。(更正)

答案 1 :(得分: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()
  9. 创建临时文件
      

    我什么时候使用?

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

答案 2 :(得分:5)

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

在第7行中,您将在参数调用中创建一个对象。所以这是一个错误。

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