Оптимизация возвращаемого значения при возврате по ссылке

Я прочитал много статей об оптимизации возвращаемого значения. Тем не менее, я не уверен, что полностью понимаю, происходит ли это в следующем случае (адреса на самом деле всегда идентичны):

#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 ?


person Roland Sarrazin    schedule 18.02.2013    source источник
comment
Спасибо за выпуск. Сначала я говорил о каскадировании, так как мой фактический вариант использования заключался в рекурсивном возврате ссылки через иерархию наследования. Но, в конце концов, вопрос фактически не зависит от наследования, что теперь отражено в отредактированном заголовке.   -  person Roland Sarrazin    schedule 18.02.2013


Ответы (2)


Всегда ли возврат по ссылке гарантирует отсутствие вызова конструктора копирования?

да. Когда вы передаете или возвращаете по ссылке (в отличие от передачи/возврата по значению), копия не создается.

происходит ли здесь RVO?

Поскольку вы возвращаетесь по ссылке, RVO здесь ни при чем. RVO — это метод оптимизации, заключающийся в устранении избыточной копии, создаваемой при возвращении по значению.

RVO может иметь место, если у вас есть такая функция:

Type GetType()
{
    Type instance;
    //...
    return instance;
}
//...
Type t = GetType();

затем с помощью RVO компилятор попытается устранить избыточные вызовы копирующего конструктора и деструктора, что означает, что локальный instance из функции GetType будет присвоен переменной t без копирования. созданный.

person LihO    schedule 18.02.2013

Всегда ли возврат по ссылке гарантирует отсутствие вызова конструктора копирования?

RVO — это метод оптимизации. Это не гарантируется стандартом. Большинство компиляторов будут применять RVO, когда вы возвращаете по значению.

virtual Type & GetType()
        ^^^^^^

Здесь вы возвращаете по ссылке, что означает, что не нужно создавать копию, поэтому нет накладных расходов на вызов конструктора копирования и, следовательно, нет возможности или области действия RVO.

адреса на самом деле всегда идентичны

На самом деле адреса всегда идентичны, потому что они являются адресами одного и того же члена класса.

person Alok Save    schedule 18.02.2013