2013-05-11 2 views
6

Я знаю, что в C++ 03 привязка non-const не может быть привязана к значениям r.Является ли оно обязательным для привязки не-const lvalue-ссылок на rvalues ​​в C++ 11? (Изменено)

T& t = getT(); недействителен, и в C++ 11 мы можем сделать это: T&& t = getT();, но как насчет вышеуказанного кода, должно ли это работать в C++ 11?

Я проверил коды ниже с VS11:

Foo getFoo() { 
    return Foo(); 
} 

void fz(Foo& f) { 
} 

int getInt() { 
    return int(); 
} 

void iz(int& i) { 
} 

int main() { 
    { 
    Foo& z = getFoo(); //ok 
    fz(getFoo()); //ok 

    int& z2 = getInt(); //error: initial value of reference to non-const must be an lvalue 
    iz(getInt()); //same as above 
    } 
} 

Foo является пользовательский класс, я не понимаю, почему первые две строки compiles.The временная ссылка на z разрушается в конце внутренней объем основного. Стандарт говорит об этом?

class Foo { 
public: 
    Foo() { 
    std::cout << "constructed\n"; 
    } 
    ~Foo() { 
    std::cout << "destructed\n"; 
    } 
}; 

Я только что видел подобный вопрос: One VS2010 bug ? Allowing binding non-const reference to rvalue WITHOUT EVEN a warning?

+4

Интересно, как * несколько * Objective-C или Java программисты задают вопросы о языке, ориентированных на эзотерике, как «Справедливо ли связывать rvalues для не-const lvalue-reference ...? " Или нужно заниматься такими вещами, как «временные ссылки ... разрушенные в конце внутреннего пространства». Just sayin ';) – paulsm4

+0

Не могли бы вы опубликовать, как вы определили Foo. – Gisway

+0

правила привязки не изменились wrt Lvalue ссылки AFAIK –

ответ

5

Должно ли это работать в C++ 11?

Нет, не следует.

Foo это пользовательский класс, я не понимаю, почему первые две строки составляет

Он компилирует только с MSVC. MSVC имеет (возможно полезный) расширение компилятора, что позволяет привязывать lvalues ​​пользовательских типов к значениям r, но сам стандарт запрещает это. См., Например, this live example, где GCC 4.7.2 отказывается компилировать ваш код.

Знает ли стандарт об этом?

Действительно, действительно. По пункту 8.5.3/5 C++ 11 Стандарт на:

Ссылка на тип «cv1 T1» инициализируется выражением типа «cv2 T2» следующим образом:

- Если ссылка именующее справочно- выражение инициализатора

- это именующий (но не битовое поле), и «cv1 T1» является ссылкой совместит с «cv2 T2» или

- имеет тип класса (то есть T2 - тип класса), где T1 не относится к T2 и может быть , неявно преобразованный в значение l типа «cv3 T3», где «cv1 T1» является ссылочным-совместимым с «cv3 T3» [...],

то ссылка связана с выражением инициализатора-значением в первом случае, и в результате именующее конверсии во втором случае (или, в любом случае, чтобы соответствующий подобъект базового класса объекта ). [...]

[...]

- В противном случае, ссылка должна быть именующей ссылкой на энергонезависимый тип сопзЬ (т.е. CV1 должен быть Const), или ссылка должна быть ссылкой rvalue. [Пример:

double& rd2 = 2.0; // error: not an lvalue and reference not const 
int i = 2; 
double& rd3 = i; // error: type mismatch and reference not const 

-end пример]

0

Нет, вы не можете связать временное с неконстантной ссылкой Lvalue.

T f(); 

T& t1 = f(); // won't compile 
const T& t2 = f(); // OK 
T&& t3 = f(); // OK 

Это функция безопасности. Мутирование временного значения lvalue, которое вот-вот должно умереть, скорее всего, является логической ошибкой, поэтому язык не допускается.

Обратите внимание, что в связи с РВО, чем на практике:

T&& t3 = f(); 

и

T t3 = f(); 

являются equivilent.

Смежные вопросы