В чем разница между (типом) значением и типом (значением)?
В чем разница между
(type)value
и
type(value)
в С++?
Ответы
Ответ 1
Нет никакой разницы; по стандарту (п. 5.2.3):
Спецификатор простого типа (7.1.5), за которым следует заключенный в скобки список выражений, строит значение указанного типа с учетом списка выражений. Если список выражений является одним выражением, выражение преобразования типа эквивалентно (в определенности и, если определено по смыслу), в соответствующее выражение (5.4).
Поскольку вопрос задает разницу между type(value)
и (type)value
, нет никакой разницы.
Если и только если вы имеете дело с разделенным запятыми списком значений, может быть разница. В этом случае:
Если в списке выражений указано более одного значения, тип должен быть классом с соответствующим объявленным конструктором (8.5, 12.1), а выражение T (x1, x2,...) эквивалентно фактически объявлению T t (x1, x2,...); для некоторой изобретенной временной переменной t, результатом которой является значение t как rvalue.
Как указывал Трубадур, существуют определенные имена типов, для которых версия type(value)
просто не будет компилироваться. Например:
char *a = (char *)string;
будет компилироваться, но:
char *a = char *(string);
не будет. Один и тот же тип с другим именем (например, созданный с помощью typedef
) может работать:
typedef char *char_ptr;
char *a = char_ptr(string);
Ответ 2
Нет никакой разницы; стандарт С++ (выпуски 1998 и 2003 годов) ясно из этого момента. Попробуйте следующую программу, убедитесь, что вы используете совместимый компилятор, например, бесплатный предварительный просмотр в http://comeaucomputing.com/tryitout/.
#include <cstdlib>
#include <string>
int main() {
int('A'); (int) 'A'; // obvious
(std::string) "abc"; // not so obvious
unsigned(a_var) = 3; // see note below
(long const&) a_var; // const or refs, which T(v) can't do
return EXIT_SUCCESS;
}
Примечание: unsigned(a_var)
отличается, но показывает один из способов, что точные жетоны могут означать что-то еще. Он объявляет переменную с именем a_var
типа unsigned и не является литой. (Если вы знакомы с указателями на функции или массивы, подумайте, как вы должны использовать parens вокруг p
в типе типа void (*pf)()
или int (*pa)[42]
.)
(Предупреждения производятся, поскольку эти утверждения не используют значение и в реальной программе, которая почти наверняка будет ошибкой, но все еще работает. У меня просто не было сердца, чтобы изменить ее после создания всей строки до.)
Ответ 3
Нет никакой разницы, если оба являются приведениями, но иногда "type (value)" не является литой.
Здесь пример стандартного черновика N3242, раздел 8.2.1:
struct S
{
S(int);
};
void foo(double a)
{
S w( int(a) ); // function declaration
S y( (int)a ); // object declaration
}
В этом случае 'int (a)' не является актом, потому что 'a' не является значением, это имя параметра, окруженное резервными скобками. В документе указано
Неоднозначность, возникающая из-за сходства между функциональным стилем и заявка, упомянутая в 6.8, может также возникать в контексте декларации. В этом контексте выбор между функцией объявление с избыточным набором круглых скобок вокруг параметра имя и объявление объекта с помощью функции-стиля в качестве инициализатор. Так же как и для двусмысленностей, упомянутых в 6.8, разрешение - рассмотреть любую конструкцию, которая могла бы быть объявить декларацию.
Ответ 4
В c нет type (value)
, тогда как в c/С++ разрешены как type (value)
, так и (type) value
.
Ответ 5
Чтобы проиллюстрировать ваши параметры на С++ (только один имеет проверку безопасности)
#include<boost/numeric/conversion/cast.hpp>
using std::cout;
using std::endl;
int main(){
float smallf = 100.1;
cout << (int)smallf << endl; // outputs 100 // c cast
cout << int(smallf) << endl; // outputs 100 // c++ constructor = c cast
cout << static_cast<int>(smallf) << endl; // outputs 100
// cout << static_cast<int&>(smallf) << endl; // not allowed
cout << reinterpret_cast<int&>(smallf) << endl; // outputs 1120416563
cout << boost::numeric_cast<int>(smallf) << endl; // outputs 100
float bigf = 1.23e12;
cout << (int)bigf << endl; // outputs -2147483648
cout << int(bigf) << endl; // outputs -2147483648
cout << static_cast<int>(bigf) << endl; // outputs -2147483648
// cout << static_cast<int&>(bigf) << endl; // not allowed
cout << reinterpret_cast<int&>(bigf) << endl; // outputs 1401893083
cout << boost::numeric_cast<int>(bigf) << endl; // throws bad numeric conversion
}