Неоднозначность стандарта C ++ - PullRequest
1 голос
/ 06 августа 2020

Согласно этому коду:

#include <iostream>
using namespace std;
struct T {
    T() { cout << "default"<<endl; }
    T(string s) { cout << "ctor "<< endl; }
    T(const T& t) { cout << "copy ctor"<< endl; }
};
int main()
{
    T x = T(T(T()));
    return 0;
}

вывод:

default

и согласно стандарту :

(17 ) Семантика инициализаторов следующая. Тип назначения - это тип инициализируемого объекта или ссылки, а исходный тип - это тип выражения инициализатора. Если инициализатор не является одиночным выражением (возможно, заключенным в скобки), тип источника не определен.

.....

(17.6.1) Если выражение инициализатора является prvalue и cv-неквалифицированная версия исходного типа является тем же классом, что и класс назначения, выражение инициализатора используется для инициализации объекта назначения. [Пример: Т х = Т (Т (Т ())); вызывает конструктор по умолчанию T для инициализации x. - конечный пример]

он дает тот же результат в c ++ 11 (GNU G CC v7.1.1)

Первый вопрос: определен ли исходный тип в этот оператор?

T x = T(T(T()));

Теперь, если мы добавим эту функцию к этому коду:

string f(T t) {return "str";}

и заменим T x = T(T(f(T()))); на T x = T(T(T()));

вывод:

default
ctor

теперь определен тип источника?

не T() выражение инициализатора?

если да Согласно стандарту конструктор по умолчанию должен быть вызван, но почему T(string s) вызывается для x?

1 Ответ

4 голосов
/ 06 августа 2020

Определен ли тип источника в этом операторе?

T x = T(T(T()));

Да, потому что T(T(T())) - это одно выражение; оно может быть заключено в паранансы, как в этом случае.

Те же рассуждения применимы к

T(T(f(T())))

, так как это тоже одно выражение.

не является выражением инициализатора T ()?

В общем, конечно, но не в вышеуказанных случаях. Все выражение между = и ; является выражением инициализатора.

, но почему для x вызывается T (строка s)?

Потому что существует явный вызов f, который возвращает string, и этот аргумент используется для создания T, который вызывает конструктор string.

T x = T(  T(f(  T()  ))  );
             // ^^^      calls the default constructor
       // ^^^^^^^^^^^^^  calls the string constructor
   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...