Подтвердить что ты не робот

Создание экземпляра класса

Какая разница между строками 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;
}
4b9b3361

Ответ 1

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

Создает объект типа Foo в динамической памяти. foo1 указывает на это. Как правило, вы не будете использовать raw-указатели в С++, а скорее умный указатель. Если Foo был POD-типом, это выполнило бы инициализацию значения (оно здесь не применяется).

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

Идентичен ранее, поскольку Foo не является типом POD.

   /* 3 */ Foo foo3;

Создает объект Foo с именем foo3 в автоматическом хранилище.

   /* 4 */ Foo foo4 = Foo::Foo();

Использует копию-инициализацию для создания объекта Foo с именем foo4 в автоматическом хранилище.

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );

Использует конструктор преобразования Bar для создания объекта типа Bar в динамическом хранилище. bar1 является указателем на него.

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

То же, что и раньше.

   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );

Это просто недопустимый синтаксис. Вы не можете объявить там переменную.

   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );

Будет работать и работать по тому же принципу с 5 и 6, если bar3 не был объявлен в 7.

5 и 6 содержат утечки памяти.

Синтаксис вроде new Bar ( Foo::Foo() ); не является обычным. Обычно это new Bar ( (Foo()) ); - дополнительная скобка для наиболее неприятного анализа. (исправлено)

Ответ 2

  • Выделяет некоторую динамическую память из свободного хранилища и создает объект в этой памяти, используя свой конструктор по умолчанию. Вы никогда не удаляете его, поэтому происходит утечка памяти.
  • Точно так же, как 1; в случае пользовательских типов скобки необязательны.
  • Выделяет некоторую автоматическую память и создает объект в этой памяти с использованием своего конструктора по умолчанию. Память освобождается автоматически, когда объект выходит из области видимости.
  • Аналогично 3. По идее, именованный объект foo4 инициализируется построением по умолчанию, копированием и уничтожением временного объекта; обычно это устраняется, давая тот же результат, что и 3.
  • Выделяет динамический объект, затем инициализирует вторую, копируя первый. Оба объекта просочились; и нет способа удалить первый, так как вы не указали на него указатель.
  • Точно так же, как 5.
  • Не компилируется. Foo foo5 - это объявление, а не выражение; аргументы функции (и конструктора) должны быть выражениями.
  • Создает временный объект и инициализирует динамический объект, копируя его. Протекает только динамический объект; временное уничтожается автоматически в конце полного выражения. Обратите внимание, что вы можете создать временное значение только с Foo(), а не с эквивалентом Foo::Foo() (или действительно Foo::Foo::Foo::Foo::Foo())

Когда я использую каждый?

  • Не делайте, если вам не нравятся ненужные украшения вашего кода.
  • Если вы хотите создать объект, который выделяет текущую область. Не забудьте удалить его, когда вы закончите с ним, и научитесь использовать интеллектуальные указатели для более эффективного управления жизнью.
  • Если вам нужен объект, который существует только в текущей области.
  • Не думайте, если вы думаете, что 3 выглядит скучно и что добавить ненужное украшение.
  • Не делайте этого, потому что он утечки памяти без шансов на восстановление.
  • Не делайте этого, потому что он утечки памяти без шансов на восстановление.
  • Не нужно, потому что он не будет компилироваться
  • Если вы хотите создать динамический Bar из временного Foo.

Ответ 3

Строки 1,2,3,4 вызовут конструктор по умолчанию. Они по сути различны, поскольку 1,2 - динамически созданный объект, а 3,4 - статически созданные объекты.

В строке 7 вы создаете объект внутри вызова аргумента. Таким образом, это ошибка.

И строки 5 и 6 являются приглашением на утечку памяти.