2009-10-30 3 views

ответ

50

Нет никакой разницы; в соответствии с стандартом (§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); 
+0

Только для встроенных типов. – Troubadour

+7

Ум, нет никакой разницы. +1 –

+2

Ну, может быть :) Но как насчет типов нетипичных указателей? – Troubadour

13

Там нет никакой разницы; стандарт C++ (выпуски 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 и не является литой. (Если вы знакомы с указателями на функции или массивы, подумайте, как вы должны использовать скобки вокруг p в типе, как void (*pf)() или int (*pa)[42].)

(Предупреждения произведены, поскольку эти заявления не использовать значение и в реальной программе, которая почти наверняка была бы ошибкой, но все по-прежнему работает. У меня просто не было сердца, чтобы изменить ее после того, как все выстроилось в линию.)

+0

Хорошее форматирование кода, было ли это предназначено? – squelart

+2

@ squelart: Не поначалу, но как только он приблизился, я работал с ним, и у меня просто не было сердца, чтобы изменить его, чтобы избавиться от предупреждений. – 2010-03-06 04:25:07

6

Нет никакой разницы, когда оба являются приведениями, но иногда '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 (а)» не литая, потому что «а» не является значением, то параметр имя, окруженное резервными скобками. В документе говорится

двусмысленности, возникающая из-за сходство между функцией стилем гипсом и декларацией, упомянутой в 6.8 также может происходить в контексте декларации. В этом контексте выбор осуществляется между объявлением функции с избыточным набором круглых скобок вокруг имени параметра и объявлением объекта с использованием функции-стиля в качестве инициализатора . Как и в случае неопределенностей, упомянутых в 6.8, резолюция заключается в рассмотрении любой конструкции, которая может быть объявлением декларации .

1

В с нет type (value), в то время как в C/C++ и type (value)(type) value и разрешены.

0

Чтобы проиллюстрировать свои варианты в C++ (только один имеет проверку безопасности)

#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 
} 
Смежные вопросы