Значение на левой стороне
Почему этот код компилируется? Я думал, что значения, возвращаемые ctor, не находятся в памяти и поэтому не могут использоваться как значения.
#include <iostream>
#include <vector>
class Y {
public :
explicit Y(size_t num = 0)
: m_resource {std::vector<int>(num)}
{
}
std::vector<int> m_resource;
};
int main(int argc, const char * argv[]) {
Y(1) = Y(0); // WHAT?!?
return 0;
}
2 ответа
Синтезированный оператор присваивания объявляется как один из них (если он может быть синтезирован и не объявлен как удаленный) согласно пункту 18 12.8 [class.copy]:
Y& Y::operator=(Y const&)
Y& Y::operator=(Y&)
()
То есть, как и для любой другой функции-члена, которая специально не объявлена с ref-определителями, она применима к rvalue.
Если вы хотите запретить временный объект в левой части присваивания, вам необходимо объявить его соответствующим образом:
class Y {
public :
explicit Y(std::size_t num = 0);
Y& operator= (Y const&) & = default;
};
Стандарт использует квалификатор ref для &
перед = default
, Соответствующее предложение N2439. Я не знаю, где есть хорошее описание реф-квалификаторов. Есть некоторая информация по этому вопросу.
Не уверен, где вы получили это конкретное правило. Если есть, то эмпирическое правило будет (от Скотта Мейерса): если у него есть имя, это lvalue.
В этом случае вы создаете временный объект и передаете его в метод / функцию назначения. С этим проблем нет. На самом деле, это может даже иметь смысл сделать, как в
// Applies foo to a copy, not the original.
(Y(1) = y).foo()
Правда, что Y(*)
здесь нет имен, и, следовательно, они являются значениями.