2017-01-27 21 views
3

У меня есть объект с именем Thing, его конструктор принимает int.C++ стиль вызова конструктора

Этот код работает, как ожидалось:

Thing thing(5);

Однако, случайно я написал следующее:

Thing thing = Thing(5); // note: no 'new'

И получил ошибку no matching constructor for initialization of 'Thing'. Каков фактический смысл последнего кода? Я знаю, что это значит, если я нахожу там new, но без нового, что это значит?

+0

Как это происходит? Я не использовал «явный» сам где-либо –

+0

@WhiZTiM 'explicit' помешал бы вместо этого вместо' Thing thing = 5'. – rom1v

+3

Показать полное определение класса 'Thing' или, по крайней мере, всех его конструкторов. –

ответ

9

Thing thing(5); is direct initliazation, thing строится по специальному конструктору (то есть Thing::Thing(int)) напрямую.

Thing thing = Thing(5);copy initialization, что не является точной, чем прямая инициализация. Но для этого случая, так как C++ 17, он будет напрямую ссылаться на Thing::Thing(int), чтобы построить объект, тогда он имеет тот же эффект с прямой инициализацией здесь.

Во-первых, если T является типом класса и инициализатор является prvalue выражение, CV-неквалифицированным тип тот же класс, как T, выражение инициализатора самого, а что временное материализовался из него, используется для инициализации объект назначения: см. copy elision

Прежде чем C++ 17, второй случай (т.е. инициализация копирования) требует, чтобы конструктор копирования/перемещения был доступен и не явным; если это так, и вы используете компилятор, не поддерживающий C++ 17, что вызовет ошибку.

Если T типа класса и резюме-неквалифицированная версия типа other является T или класса, производным от T, не-явных конструкторов T рассматриваются и лучший матч выбираются разрешение перегрузки , Затем конструктор вызывается для инициализации объекта.

Обратите внимание, что с C++ 17 код будет скомпилирован. Согласно правилу copy elision, конструкторы копирования/перемещения не обязательно должны быть доступны и explicit для этого случая.

При следующих обстоятельствах составители должны опускать от копирования и MOVE- Конструкторы класса объектов, даже если копировать/перемещать конструктор и деструктор имеют наблюдаемые побочные эффекты:

  • При инициализации, если выражение инициализатора является prvalue, а cv-неквалифицированная версия типа источника - это тот же класс, что и класс назначения , выражение инициализатора используется для инициализировать целевой объект:

    T x = T(T(T())); // only one call to default constructor of T, to initialize x 
    
+0

IMO вы говорите о 'Thing thing = 5', а не' Thing thing = Thing (5) '. В последнем случае создание конструктора 'Thing (int)' 'explicit' в порядке, как только будет создан конструктор-копир (но этот конструктор-копия не должен быть« явным »). – rom1v

10
Thing thing = Thing(5); 

требует (не- explicit) копию (или переместить) -constructor быть определены:

Thing(const Thing &); 

(даже если это не называется по соображениям оптимизации).

+0

Я вижу, так что формулировка делает «Вещь», а затем копирует ее (довольно бессмысленно). –

+0

Вы не можете заключить это, не видя конструкторов классов/членов – P0W

+2

@ P0W, так как 'Thing thing (5);' работает, есть хотя бы конструктор 'Thing (int)' ('explicit' или нет). Если 'Thing thing = Thing (5)' не работает, IMO мы можем заключить, что отсутствует экземпляр (/ move) -constructor. Не могли бы вы привести встречный пример? – rom1v

Смежные вопросы