2012-05-16 10 views
5

Я написал следующий код, чтобы проверить это:Можно ли привязать временные ссылки к неконстантным ссылкам?

struct X 
{ 
    char* x; 
    X() 
    { 
     x = new char('a'); 
    } 
    ~X() 
    { 
     *x = 'b'; 
     delete x; 
    } 
}; 

void foo(const X& x) 
{ 
} 
void goo(X& x) 
{ 
} 

int main() 
{ 
    foo(X()); 
    goo(X()); 
} 

деструкторов для временных называется после как функции выхода, но я думал, что вы можете связывать только временный к const ссылке. Почему тогда работает goo?

Неправильно ли это UB и MSVS, или все в порядке?

+0

«Это UB и MSVS ошибочно» - если UB MSVS * не может быть ошибочным по определению, потому что проявления UB включают «все работает как ожидалось» (для каждого значения «как ожидалось»). –

+0

Это обман по другому вопросу. И да, MSVC здесь непослушный, проверьте идеон: http://ideone.com/zykx9. – Pubby

+1

Возможный дубликат [Как ссылка не-const ссылается на временный объект?] (Http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to -a-time-object) – iammilind

ответ

3

Это незаконно. Соответствующая реализация диагностирует его (то есть он должен хотя бы предупреждать), но MSVC++ разрешает его как расширение.

Или ошибка, если вы недобрый, но IIRC причина, по которой они до сих пор разрешают это, для долговременных устаревших причин: номинально поддерживать код, написанный для MSVC++, до того, как C++ был стандартизирован, но, разумеется, после того, как вы разрешите людям писать это, они пишут это случайно и в новом коде, так что наследие живет. Если это преднамеренно, то это (неправильная) функция, а не ошибка, не так ли? В любом случае, соответствующая реализация - , требуется для диагностики плохо сформированных программ, поэтому, если вы не получите предупреждение, компилятор не соответствует.

+0

Мне не нравится слово «ошибка»; ошибка - гораздо более точное слово. И если это преднамеренно, то это не ошибка, по крайней мере, не ошибка программирования. (Решение поддержать его _is_ ошибка, поскольку правило, запрещающее привязку к неконстантной ссылке, предшествует первому компилятору MS C++ не менее чем на 5 лет. Когда MS представила свой первый компилятор C++, CFront уже предупредил об использовании устаревшей функции в этот случай.) –

+0

@James: учитывая, что MS «обнимает и расширяет» подход к стандартам, я могу себе представить, сколько веса они дали предварительным стандартам «правила». В конце концов, кто же, по мнению Бьярне, он, изобретатель языка или что-то еще? ;-) –

+1

Обратите внимание, что, по крайней мере, для VS2008 VS будет выдавать * предупреждение * для использования любых расширений компилятора, включая этот. Существует даже компилятор, чтобы отключить их. Также как для GCC. Итак, если вы собираетесь обвинить MS в том, что она «охватывает и расширяет», не следует ли включать бесчисленные расширения GCC, которые некоторые проекты не будут компилировать без? –

1

Это, по-видимому, расширение MS. В GCC 4.3.4, например, он fails to compile, со следующим сообщением:

prog.cpp: In function ‘int main()’: 
prog.cpp:25: error: invalid initialization of non-const reference of type ‘X&’ from a temporary of type ‘X’ 
prog.cpp:18: error: in passing argument 1 of ‘void goo(X&)’