Я прочитал много статей об оптимизации возвращаемого значения. Тем не менее, я не уверен, что полностью понимаю, происходит ли это в следующем случае (адреса на самом деле всегда идентичны):
#include "stdafx.h"
class Type
{
public:
Type(int a) { m_a = a; }
private:
Type(const Type & other) {}
int m_a;
};
class Base
{
public:
Base() : instance(42) {}
virtual Type & GetType()
{
printf("Base: Address of instance: %i\n", &instance);
return instance;
}
private:
Type instance;
};
class Derived : public Base
{
public:
virtual Type & GetType()
{
printf("Derived\n");
return Base::GetType();
}
};
int main()
{
printf("Base class\n");
Base b;
printf("Main: Address of instance: %i\n", &(b.GetType()));
printf("\nDerived class\n");
Derived d;
printf("Main: Address of instance: %i\n", &(d.GetType()));
}
Всегда ли возврат по ссылке гарантирует, что конструктор копирования не будет вызван?
Или РВО здесь происходит?
Всегда ли возврат по ссылке гарантирует, что конструктор копирования не будет вызван?
Да. Когда вы передаете или возвращаете по ссылке (в отличие от передачи / возврата по значению), копия не создается.
является РВО здесь происходит?
Поскольку вы возвращаетесь по ссылке, RVO здесь не имеет к этому никакого отношения. RVO — это метод оптимизации, который заключается в устранении избыточной копии, создаваемой при возвращая по значению.
RVO может занять место, если у вас есть такая функция:
Type GetType()
{
Type instance;
//...
return instance;
}
//...
Type t = GetType();
тогда с RVO компилятор попытается устранить лишнее конструктор копирования а также деструктор звонки, что означает, что местный instance
от GetType
функция будет назначена в переменную t
без создания копии.
Всегда ли возврат по ссылке гарантирует, что конструктор копирования не будет вызван?
RVO — это метод оптимизации. Это не гарантируется стандартом. Большинство компиляторов будут применять RVO, когда вы возврат по значению.
virtual Type & GetType()
^^^^^^
Вы возвращение по ссылке здесь, что означает, что не нужно создавать копию, поэтому нет затрат на вызов конструктора копирования и, следовательно, нет ни шансов, ни области действия RVO.
адреса на самом деле всегда идентичны
Адреса на самом деле всегда идентичны, потому что это адреса одного и того же члена класса.