Значение на левой стороне

Почему этот код компилируется? Я думал, что значения, возвращаемые 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(*) здесь нет имен, и, следовательно, они являются значениями.

Другие вопросы по тегам