В чем разница между (типом) значением и типом (значением)?

StackOverflow https://stackoverflow.com/questions/1652396

  •  22-07-2019
  •  | 
  •  

Вопрос

В чем разница между

(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 (х1, х2, ...);для некоторой изобретенной временной переменной t, результатом чего является значение t как rvalue.

Как указывал Трубадур, существуют определенные названия типов, для которых type(value) версия просто не скомпилируется.Например:

char *a = (char *)string;

скомпилируется, но:

char *a = char *(string);

не будет.Тот же тип с другим именем (например, созданный с помощью typedef) может работать, хотя:

typedef char *char_ptr;

char *a = char_ptr(string);

Другие советы

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

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

Нет никакой разницы, когда оба являются приведениями, но иногда «тип (значение)» не является приведением.

Вот пример из проекта стандарта 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, решение состоит в том, чтобы рассмотреть любую конструкцию, которая может быть декларация декларация.

в с нет type (value), тогда как в c/c++ оба type (value) и (type) value разрешается.

Чтобы проиллюстрировать ваши варианты на 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
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top