В чем разница между
(type)value
и
type(value)
в С++?
В чем разница между
(type)value
и
type(value)
в С++?
Нет никакой разницы; по стандарту (п. 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);
Нет никакой разницы; стандарт С++ (выпуски 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]
.)
(Предупреждения производятся, поскольку эти утверждения не используют значение и в реальной программе, которая почти наверняка будет ошибкой, но все еще работает. У меня просто не было сердца, чтобы изменить ее после создания всей строки до.)
Нет никакой разницы, если оба являются приведениями, но иногда "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, разрешение - рассмотреть любую конструкцию, которая могла бы быть объявить декларацию.
В c нет type (value)
, тогда как в c/С++ разрешены как type (value)
, так и (type) value
.
Чтобы проиллюстрировать ваши параметры на С++ (только один имеет проверку безопасности)
#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
}