Конструктор типа int

Учитывая стоимость, эти случаи одинаковы?

// case 1 int a = 5; // case 2 int a (5); // case 3 int a; a = 5 

Первая и вторая точно такие же, как и инициализация . Третье – другое, поскольку это назначение . Эти различия соответствуют стандарту C ++. Тем не менее, компилятор может рассматривать все три одинаково!

Три синтаксиса разные, несите меня, а я использую определенный пользователем тип вместо int, я вернусь к int позже.

 T a(5); // Direct initialization T b = 5; // Implicit conversion (5->tmp) + copy-initialization T c; c = 5; // Default initialization + assignment 

В первом случае объект a строится с помощью конструктора, который принимает int или тип, который может быть неявно преобразован из int .

 struct T { T( int ); // T a(5) will call this directly }; 

Во втором случае временный объект типа T создается неявным преобразованием из int , а затем это временное используется для копирования конструкции b . Компилятор может оптимизировать код и выполнять только неявное преобразование вместо конечного объекта (вместо того, чтобы использовать его для создания временного. Но все ограничения должны быть проверены :

 class T { T( T const & ); public: explicit implicit T( int ); }; int main() { T b = 5; // Error 1: No implicit conversion from int to T. // Fix: remove the `explicit` from the constructor // Error 2: Copy constructor is not accessible } 

Третий случай – построение по умолчанию, за которым следует назначение. Требования к типу заключаются в том, что он может быть сконфигурирован по умолчанию (есть конструктор без аргументов или вообще не существует никакого определяемого пользователем конструктора, и компилятор будет неявно определять его). Тип должен быть назначен из int или должно быть неявное преобразование из int в тип U который может быть назначен T Как вы видите, требования к типу в случаях дерева различаются.

Помимо семантики различных операций, существует и другая важная разница, не все из них могут использоваться во всех контекстах. В частности, в списке инициализации в classе вы не можете использовать версию инициализации с неявным преобразованием + копии , и вы можете иметь только первую половину стандартной конструкции + .

 // OK // error // ok but different struct test { struct test { struct test { T x; T x; T x; test(int v) : x(v) {} test(int v) : x=5 {} test( int v ) { x = v; } 

В первом случае атрибут x непосредственно инициализируется значением v . Второй случай – синтаксическая ошибка. Третий случай, первый по умолчанию инициализирует, а затем назначает внутри тела конструктора.

Возвращаясь к примеру int , все требования удовлетворяются типом, поэтому почти нет разницы в коде, который генерирует компилятор для трех случаев, но все же вы не можете использовать int b = 5; версии внутри списка инициализаторов для инициализации целочисленного атрибута. Более того, если class имеет атрибут member, который является постоянным целым числом, то вы не можете использовать эквивалент int c; c =5; int c; c =5; (третий столбец выше), поскольку атрибут member становится const когда он входит в блок конструктора, то есть x = v; выше будет пытаться изменить константу, и компилятор будет жаловаться.

Что касается стоимости, которую каждый из них имеет, если они могут быть использованы вообще, они несут ту же стоимость для int (для любого типа POD), но не так для определенных пользователем типов, у которых есть конструктор по умолчанию, и в этом случае T c; c = 5; T c; c = 5; будет нести стоимость строительства по умолчанию, за которой следует стоимость задания . В двух других случаях стандарт явно указывает, что компилятору разрешено генерировать точный код (после проверки ограничений).

Для первых двух не будет никакой разницы.

Из стандартных документов, 8.5.11 ,

Форма инициализации (с использованием скобок или =) обычно незначителен, но имеет значение, когда инициализатор или инициализируемый объект имеет тип classа; Смотри ниже. Инициализатор в скобках может быть списком выражений только тогда, когда инициализированный объект имеет тип classа.

Третий – это не инициализация, а назначение.

И учитывая стоимость,

В первых двух случаях вы создаете целое число со значением 5.

В третьем случае вы создаете целое число с неопределенным значением и заменяете его на 5 ..

Если вы используете оптимизирующий компилятор, все они будут скомпилированы с тем же кодом. Таким образом, все они имеют одинаковую стоимость.

Да, все они оценивают то же самое ассемблерное представление. Вы можете протестировать это, например, с помощью GCC, написав фиктивную функцию, а затем создав выход ассемблера: g++ -S file.cxx -o file.s

  • Сохранение пользовательских атрибутов в NSAttributedString
  • Определите, является ли строка C допустимым int в C
  • Трассировка стека на C ++ при исключении
  • Вставка в вектор спереди
  • C # Как найти, подключено ли событие
  • Как изменить шаблоны Visual Studio для нового classа / интерфейса C #?
  • Чтение электронной почты MS Exchange в C #
  • Как запустить Visual C ++ 6 IDE в Windows Vista или выше?
  • Неявное преобразование при перегрузке операторов для classов шаблонов
  • Почему Random.Next () всегда возвращает один и тот же номер
  • __builtin_prefetch, сколько он читает?
  • Давайте будем гением компьютера.