Я использую Visual Studio Express 2013 и немного дурачусь, пытаясь узнать о разных вещах в C ++.
Я наткнулся на интересную ошибку в компиляторе, когда кажется, что он не создает временный объект при явном приведении типов к тому же типу, что и ссылка.
#include <iostream>
using namespace std;
int main()
{
int number; // float number;
number = 2;
const int& plainref_i = number;
const int& recastref_i = (int)number; // this goes wrong if number is int
const float& plainref_f = number;
const float& recastref_f = (float)number; // this goes wrong if number is float
number = 3;
std::cout << plainref_i << "\n";
std::cout << recastref_i << "\n";
std::cout << plainref_f << "\n";
std::cout << recastref_f << "\n";
return 0;
}
Это будет при компиляции в VS, приведет к следующему выводу:
3
3
2
2
Но скомпилированный с gcc, приводит к следующему выводу:
3
2
2
2
Если я заменю «int number;» с «числом с плавающей точкой»; Я получаю в VS:
2
2
3
3
и с gcc:
2
2
3
2
Мне интересно, может ли кто-нибудь подтвердить это как ошибку и знает ли кто-нибудь о возможном обходном пути / решении.
Дано:
int number;
Результаты этого броска должны быть prvalue:
const int& recastref_i = (int)number; // this goes wrong if number is int
и поскольку вы используете константную ссылку, то она может привязываться к prvalue, и ее значение должно быть отделено от любых изменений в number
но Visual Studio имеет расширение, которое производит lvalue вместо prvalue, так что вы на самом деле получите ссылку на lvalue number
что означает любые изменения в стоимости number
будет отражено при проверке значения recastref_i
,
Команда Visual Studio рекомендует использовать /Zc:rvalueCast
флаг, чтобы отключить это поведение (акцент мой):
Когда указана опция / Zc: rvalueCast, компилятор корректно
идентифицирует ссылочный тип rvalue как результат операции приведения
в соответствии со стандартом C ++ 11. Когда опция не
указано, поведение компилятора такое же, как в Visual Studio 2012.
По умолчанию / Zc: rvalueCast отключен. Для соответствия и устранения
ошибки в использовании приведений, мы рекомендуем использовать / Zc: rvalueCast.
в отличие от /Za
который отключит все расширения, которые может быть проблематичным в практических сценариях.
Из проекта стандартного раздела C ++ 5.4
Явное преобразование типов (нотация приведения) параграф 1 который говорит (акцент мой):
Результат выражения (T) cast-expression имеет тип T.
результатом является lvalue, если T является ссылочным типом lvalue или rvalue
ссылка на тип функции и значение xvalue, если T является ссылкой rvalue
типу объекта; в противном случае результат является prvalue.