Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
1. Да, это так, но ничего смешного в этом не вижу. Правда, последнее время они начали исправляться, что радует: C++11/14 Core Language Features in VS 2013 and the Nov 2013 CTP.
2. Хоть какие-нибудь аргументы можно увидеть, кроме "так всегда было"?
И заодно объяснить следующее явление, нагло имеющее место не только в C++, но даже в MQL4++:
Которое имеет наглость ещё и работать, как ожидается:
Как хорошо видно, в конструкции "int i = 7, j = i + 1;" для инициализации переменной j в выражении используется даже не адрес, а значение переменной i, хотя до "завершения оператора", то есть, до ";", дело ещё не дошло. Как это сопоставить с "так всегда было"?
Что ж, наверное следует обратиться к первоисточнику и, без преувеличения, - истине в последней инстанции, то есть, к стандарту C++11 (использован текущий драфт N3690):
Совершенно ясно сказано, что точка декларации находится сразу после полного декларатора и до его инициализации, то есть, в моём примере, - на открывающей круглой скобке после имени переменной, как я и говорил. Более того, в только что процитированной мной части стандарта приведён пример, очень близкий к нашему случаю, (во внутреннем блоке, образованном { }) и далее прямо написано, что для этого случая переменная инициализируется своим собственным же (неопределённым) значением. Если уж прямо в стандарте пример приведён, - тут уж никуда не деться...
3. Это не у меня в примере "не прокатило", а утверждение stringo оказалось неверным, мой пример лишь был специально так составлен, чтобы это показать.
4. Хотелось бы ясно увидеть, как из того, что пример компилируется, следует, что конструктор есть. И ссылку на хоть какой-нибудь вменяемый документ, где утверждается, что в C++ все базовые типы имеют конструкторы.
5. gcc version 4.7.2. Не настолько и устаревший.
Нет там никакого присваивания, там - инициализация, это сильно разные вещи. Более того, в сообщении об ошибках компилятор об этом прямым текстом и заявляет, цитирую: "error C2440: инициализация:". Инициализация, а не "невозможное присваивание". В сообщениях об ошибках также сказано о том, что, цитирую: "невозможно преобразовать" и "требуется явное приведение". Ничего об обнаружении "невозможного присваивания" там не сказано. И про конструкторы ни слова. Зачем же выдумывать?
6. Я специально привёл пример, чтобы показать, что stringo ошибся. Да, суть в том, что в C++ указатель на тип данных, отличных от типа void, НЕ приводится НЕЯВНО к указателю на void. Вот, в обратную сторону - приводится НЕЯВНО, а так, как утверждал stringo - нет.
2. В Студии иначе не помню, чтобы было. Запятая, в этом случае, это перечисление операторов. По сути тоже самое, что ";".
3. Ваш пример некорректен. Там нет приведения типа (для вас явного приведения). Уже несколько раз написал это.
4. Даже не хочется отвечать на вопрос с очевидным ответом.
Конструкция типа:
говорит о том, что у типа int есть не только конструктор по умолчанию.
5. Конечно, Вам никто не будет в сообщении об ошибке рассказывать внутреннее устройство базового типа. Всё предельно разжёвано на самом высоком уровне.
Инициализация происходит в конструкторе путём присваивания. Компилятор не может понять, каким образом, указатель на тип int должен принять указатель на тип void. Наверняка, те кто писали компилятор, посчитали это возможной ошибкой программиста. Чтобы он ещё раз хорошенько подумал, зачем он так делает.
6. Ещё раз... :-( Неявное преобразование это надежда на авось. Не все классы и даже базовые типы имеют нужные конструкторы, перегруженные операторы присваивания и другие операторы с нужным типом. Поэтому надо всегда делать явное приведение типа. Для меня вовсе не существует неявного приведения типа. Всегда делаю явное. Даже слова такие забыл - явное/неявное. Оно для меня просто - приведение типа.
Кстати, последнее предложение очень сложно для понимания. Не осилил :-)
2. В Студии иначе не помню, чтобы было. Запятая, в этом случае, это перечисление операторов. По сути тоже самое, что ";".
3. Ваш пример некорректен. Там нет приведения типа (для вас явного приведения). Уже несколько раз написал это.
4. Даже не хочется отвечать на вопрос с очевидным ответом.
Конструкция типа:
говорит о том, что у типа int есть не только конструктор по умолчанию.
5. Конечно, Вам никто не будет в сообщении об ошибке рассказывать внутреннее устройство базового типа. Всё предельно разжёвано на самом высоком уровне.
Инициализация происходит в конструкторе путём присваивания. Компилятор не может понять, каким образом, указатель на тип int должен принять указатель на тип void. Наверняка, те кто писали компилятор, посчитали это возможной ошибкой программиста. Чтобы он ещё раз хорошенько подумал, зачем он так делает.
6. Ещё раз... :-( Неявное преобразование это надежда на авось. Не все классы и даже базовые типы имеют нужные конструкторы и перегруженные операторы присваивания с нужным типом. Поэтому надо всегда делать явное приведение типа. Для меня вовсе не существует неявного приведения типа. Всегда делаю явное. Даже слова такие забыл - явное/неявное. Оно для меня просто - приведение типа.
2. Значит ли это, что стандарт C++ ошибается, а компилятор от Microsoft - нет, когда он отказывается компилировать конструкцию "void *p(&p);"?
4. Очевидно, дело не в "не хочется".
Конструкция
является всего лишь прямой инициализацией:
3, 4, 5. По поводу инициализации и приведения типов (в том же параграфе 8.5):
Ничего не сказано, что инициализация - это присваивание. Начальное значение инициализируемого объекта есть значение инициализирующего выражения, и - всё.
Зато сказано, что если исходный и конечный типы не совпадают, то используются стандартные преобразования (приведения). Именно поэтому компиляторы пытаются выполнить приведение типов (строго по стандарту, кстати) и ведут речь в сообщениях об ошибках о приведении типов (conversion).
Также сказано, что если приведения типов не могут быть выполнены, инициализация "неправильно оформлена". В нашем случае не может быть выполнено приведение от 'void *' к 'int *', и поэтому инициализация "неправильно оформлена", что приводит к ошибке компиляции.
6. Дело не в том, как кто-то относится к неявному преобразованию и кто как делает.
Дело в том, что в C++ отсутствует стандартное преобразование от 'void *' к 'T *', где T - некий тип, отличный от void, а из высказывания stringo следовало, что такое преобразование есть.
Я специально составил пример, из которого стало бы ясно, что такого преобразования нет.
Надеюсь, в третий раз не будет про авось?
Попроще - можно. Стандартное преобразование от 'T *' к 'void *' в C++ - есть, а от 'void *' к 'T *' - нет. Здесь T - тип, отличный от void.
Кстати, первая конструкция "void *p(&p);" как раз это и показывает: здесь destination type - есть тип переменной, то есть, 'void *', а source type - есть 'void **', то есть, указатель на тип 'void *'. А 'void *' - есть тип, отличный от типа 'void'. И компилятор совершенно не возражает стандартно привести от 'void **' к 'void *'.
Если 'void **' и 'void *' - сложно, ну, можно завести сначала переменную типа 'int *', а потом использовать её для инициализации переменной типа 'void *'. Увидеть, что компилятор нисколько не возражает.
Потом попробовать в обратном порядке и убедиться, что теперь компилятор возражает.