(N) RVO помогает избежать ненужного копирования и создания временных объектов, когда возвращаемое значение присваивается новой переменной (таким образом избегая конструктора копирования).
Так что-то вроде этого должно быть оптимизировано RVO:
MyObj getMyObj() {
return MyObj();
}
MyObj myobj = getMyObj();
Однако произойдет ли это, когда объект сайта вызова уже существует? (Т.е. в случае, когда =
оператор используется вместо конструктора копирования). Я пытался найти литературу по этому поводу, но (N) RVO, кажется, всегда описывается в терминах избегания конструктора копирования. Не уверен, что в этом случае безопасно изменить объект сайта вызова.
MyObj myobj;
//will getMyObj() first create a temporary object and then copy it via the = operator?
myobj = getMyObj();
Нет, RVO не применяется. (N) RVO определяется в стандарте исключительно как выбор конструктора.
Мотивация заключается в том, что если конструктор MyObj()
бросает, потом во второй фрагмент кода myobj
уже существует и должен продолжать существовать в состоянии, в котором он находился до вызова getMyObj()
,
Кроме того, я не думаю, что в целом ясно, как на самом деле будет достигнуто строительство на месте. myobj
это уже построенный объект, и только operator=
«знает», как заменить любые ресурсы, которые он содержит, другими ресурсами.
Возвращаемое значение getMyObj
тем не менее, может быть создан непосредственно, и вызывающий код может получить operator=(MyObj &&)
(переместить назначение), если есть. Так что код не обязательно требуется либо создание копии, либо копирование-назначение, но оно требует назначения, которое нельзя исключить.
Если все вписано, и MyObj()
не может бросить, и у присваивания нет побочных эффектов, тогда в удачный день компилятор может применить правило «как если» и оптимизировать независимо от конкретных правил (N) RVO!
Других решений пока нет …