2014-02-18 3 views
3

В «языке программирования C++» 4 страницы издания 164:Нужна помощь пониманию «{} -initializer синтаксис минимизирует шансы неудачных преобразований»

Когда мы явно указать тип объекта, мы инициализация, У нас есть два типа для рассмотрения: тип объекта и тип инициализатор. Например:

char v1 = 12345; // 12345 is an int 
int v2 = 'c'; // 'c' is a char 
T v3 = f(); 

с помощью клавиша {} -initializer синтаксиса для таких определений, мы уменьшаем шансов на печальные превращения:

char v1 {12345}; // error : narrowing 
int v2 {'c'}; // fine: implicit char->int conversion 
T v3 {f()}; // works if and only if the type of f() can be implicitly converted to a T 

Я не совсем понимаю фразы minimize the chances for unfortunate conversions и комментарий для T v3 {f()}; что он works if and only if the type of f() can be implicitly converted to a T. Рассмотрим следующие два случая:

  • a) Если T имеет явный конструктор, принимающий аргумент типа f().
  • б) Если тип F() имеет оператор преобразования для некоторого типа X и Т имеет конструктор, принимающий аргумент типа X.

В обоих случаях, тип F() может» t неявно преобразуется в T, но T v3 {f()} хорошо сформирован, поэтому, по крайней мере, часть этого комментария кажется неприемлемой? (Также не уверены, правильная ли часть if.)
И для обоих случаев это T v3 = f();, что плохо сформировано, так что же означает здесь предложение minimize the chances for unfortunate conversions? Кажется, что {} -инициализатор фактически принимает больше форм преобразования (является ли это неудачным или нет, это другой вопрос). (Предотвращение сужения иллюстрируется в случае v1, и это понятно. Я смущен насчет v3.)

ответ

0

Фактически это конверсии по-другому, чем по умолчанию.

Используя один из ваших примеров, char x = 12345; фактически сократит это значение до последних 8 бит, так как это размер символа. С обозначением {} он вызывает ошибку, поскольку он не соответствует.

Не так было (ab) используется для получения спецэффектов, поэтому он был оставлен как опция по умолчанию в новом C++, в то время как новые обозначения используются для обеспечения лучшего поведения с меньшим количеством ошибок.

+0

Как я уже сказал в вопросе: «Предотвращение сужения проиллюстрировано в случае с v1, и это понятно. Я смущен о v3'». Спасибо, в любом случае. – goodbyeera

0

Конверсия:

char v1 = 12345; 

является несчастный, потому что это почти наверняка не то, что хочет программист:

  • либо мы хотим, чтобы тип, который может представлять значение 12345,
  • или мы использовали правильный тип, но неправильное значение

Для v3 то же самое относится, но в более сложном контексте. Первый фрагмент заставит компилятор учитывать пользовательские последовательности преобразования.Это увеличивает вероятность ошибки; в конце концов, мы можем ошибочно внедрить оператор преобразования, сделать опечатку или иным образом устроиться с круглой привязкой в ​​квадратном отверстии. Используя инициализацию списка копий, мы исключаем пользовательские последовательности преобразований, делая преобразование намного безопаснее.

Для примера и подробного объяснения того, почему это происходит, см. this question.

+0

Вопрос, на который вы добавляете ссылку, действительно задан мной, если вы еще не заметили :-) Я знаю об этом случае. Что касается вопроса здесь, меня больше смущают случаи, которые отклоняются 'T v3 = f();' но принимаются 'T v3 {f()};', как я упоминал в вопросе. С этими случаями, все же разумно сказать, что {} -инициализатор минимизирует шансы на неудачные преобразования? (И по моему личному вкусу, сценарий, отклоненный в связанном вопросе, менее печален, чем сценарий, принятый в вопросе здесь.) – goodbyeera

0

Комментарий для инициализации v3:

T v3 {f()}; // works if and only if the type of f() can be implicitly converted to a T 

не является строго правильным. Эта инициализация работает тогда и только тогда, когда тип f() может быть явно преобразован в T. Синтаксис:

T v3 = {f()}; // truly does work if and only if the type of f() 
       // can be implicitly converted to a T 

(копия-лист инициализация вместо прямого списка инициализация) действительно ли требуется преобразование быть неявным. Различие иллюстрируется с помощью этой программы:

struct T { 
    explicit T(int) {} 
}; 

int f() { return 0; } 

int main() { 
    T v3 = {f()}; 
} 

, в котором инициализация будет диагностирован как плохо сформирован, так как он выбирает явный конструктор для T (Live demo at Coliru).

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