Информация об изменениях

Сообщение Re[10]: Почему нельзя писать void ctor(); от 27.04.2017 17:10

Изменено 27.04.2017 17:30 N. I.

Re[10]: Почему нельзя писать void ctor();
CRT:

CRT>Поэтому это не очевидно — то есть непонятно на первый взгляд — в таком синтаксисе, что

CRT>
A obj=A(1024);

CRT>равно
CRT>
A obj(1024);

C++ — это вообще не тот язык, где всё становится очевидно после пары дней беглого знакомства с его правилами. Тут пока досконально не узучишь детали, не поймёшь, как оно работает.

Нечто вроде

T x = T(arg);

не является какой-то специальной конструкцией языка, это всего лишь частный случай инициализации вида

T x = a;

где в качестве a выступает некое выражение T(arg).

В отличие от общей direction-initialization

T x(a);

copy-initialization

T x = a;

предназначена специально для тех случаев, когда между инициализирующим значением и значением инициализируемого объекта есть некое достаточное родство, поэтому её использование при прочих равных условиях способствует лучшей самодокументированности кода. Сравни:

std::string const s = "text";
std::vector<int> v(42);

Здесь литерал "text" и объект s по сути представляют одну и ту же сущность — строку text. Различия состоят лишь в способе хранения этой строки и наборе доступных операций над ней.

v непосредственно после своей инициализации хранит последовательность из 42-х нулей, и эту последовательность из 42-х нулей довольно трудно назвать близкой по смыслу к самому числу 42. Конструктор vector-а, где мы указываем размер, объявлен как explicit, что как раз запрещает использование

std::vector<int> v = 42;

поэтому здесь мы вынуждены использовать direction-initialization, тем самым указывая на потенциальную возможность большого различия между смыслом того, что мы иницилизируем, и смыслом того, чем мы инициализируем. Своеобразная универсальность direction-initialization не делает её всегда лучше, чем copy-initialization, точно так же, как универсальность (T)arg не делает данный вид преобразования всегда лучше, чем более ограниченный static_cast<T>(arg).

Я не вижу особого смысла в использовании

T x = T(a);

вместо

T x(a);

где T — это классовый тип. Насколько я вижу, по правилам С++17 эти два варианта полностью идентичны. Но я и не вижу каких-либо причин запрещать первый вариант на уровне языка. Как минимум, нечто подобное вполне могло бы получиться в виде частного случая при инстанцировании какого-нибудь шаблона или раскрытии какого-нибудь макроса, и было бы странно если б оно внезапно перестало собираться.
Re[10]: Почему нельзя писать void ctor();
CRT:

CRT>Поэтому это не очевидно — то есть непонятно на первый взгляд — в таком синтаксисе, что

CRT>
A obj=A(1024);

CRT>равно
CRT>
A obj(1024);

C++ — это вообще не тот язык, где всё становится очевидно после пары дней беглого знакомства с его правилами. Тут пока досконально не узучишь детали, не поймёшь, как оно работает.

Нечто вроде

T x = T(arg);

не является какой-то специальной конструкцией языка, это всего лишь частный случай инициализации вида

T x = a;

где в качестве a выступает некое выражение T(arg).

В отличие от общей direct-initialization

T x(a);

copy-initialization

T x = a;

предназначена специально для тех случаев, когда между инициализирующим значением и значением инициализируемого объекта есть некое достаточное родство, поэтому её использование при прочих равных условиях способствует лучшей самодокументированности кода. Сравни:

std::string const s = "text";
std::vector<int> v(42);

Здесь литерал "text" и объект s по сути представляют одну и ту же сущность — строку text. Различия состоят лишь в способе хранения этой строки и наборе доступных операций над ней.

v непосредственно после своей инициализации хранит последовательность из 42-х нулей, и эту последовательность из 42-х нулей довольно трудно назвать близкой по смыслу к самому числу 42. Конструктор vector-а, где мы указываем размер, объявлен как explicit, что как раз запрещает использование

std::vector<int> v = 42;

поэтому здесь мы вынуждены использовать direct-initialization, тем самым указывая на потенциальную возможность большого различия между смыслом того, что мы иницилизируем, и смыслом того, чем мы инициализируем. Своеобразная универсальность direct-initialization не делает её всегда лучше, чем copy-initialization, точно так же, как универсальность (T)arg не делает данный вид преобразования всегда лучше, чем более ограниченный static_cast<T>(arg).

Я не вижу особого смысла в использовании

T x = T(a);

вместо

T x(a);

где T — это классовый тип. Насколько я вижу, по правилам С++17 эти два варианта полностью идентичны. Но я и не вижу каких-либо причин запрещать первый вариант на уровне языка. Как минимум, нечто подобное вполне могло бы получиться в виде частного случая при инстанцировании какого-нибудь шаблона или раскрытии какого-нибудь макроса, и было бы странно если б оно внезапно перестало собираться.