Как его время жизни возвращаемого значения расширено на объем функции вызова, когда это связывается со ссылкой константы в функции вызова?

"Если Вы возвращаете значение (не ссылка) от функции, затем связываете ее со ссылкой константы в функции вызова, ее время жизни было бы расширено на объем функции вызова".

Так: СЛУЧАЙ A

const BoundingBox Player::GetBoundingBox(void)
{
    return BoundingBox( &GetBoundingSphere() );
}

Возвращает значение типа const BoundingBox от функции GetBoundingBox()

вариант I: (Свяжите его со ссылкой константы),

const BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox();

вариант II: (Свяжите его с копией константы),

const BoundingBox l_Bbox = l_pPlayer->GetBoundingBox();

Оба хорошо работают, и я не вижу l_Bbox объект, выходящий из объема. (Хотя, я понимаю в различном, конструктора копии не вызывают и таким образом немного лучше, чем вариант II).

Кроме того, для сравнения я внес следующие изменения.

СЛУЧАЙ B

BoundingBox Player::GetBoundingBox(void)
{
    return BoundingBox( &GetBoundingSphere() );
}

с вариантами: я

BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox();

и II:

BoundingBox l_Bbox = l_pPlayer->GetBoundingBox();

Объект l_Bbox все еще не выходит объем. Как действительно "связывает его со ссылкой константы в функции вызова, ее время жизни было бы расширено на объем функции вызова", действительно расширьте время жизни объекта к объему функции вызова?

Я пропускаю что-то тривиальное здесь?

9
задан MackM 1 March 2018 в 16:56
поделиться

4 ответа

Обычно временный объект (например, возвращаемый вызовом функции) имеет время жизни, которое продолжается до конца "заключающего выражения". Однако временный объект, связанный со ссылкой, обычно имеет время жизни, "увеличенное" до времени жизни ссылки (которое может быть, а может и не быть временем жизни вызывающей функции), но есть пара исключений. Об этом говорится в стандарте 12.2/5 "Временные объекты":

Временный объект, с которым связана ссылка, или временный объект, который является полным объектом для подобъекта, с которым связан временный объект, сохраняется в течение времени жизни ссылки, за исключением случаев, указанных ниже. Временное, связанное с членом ссылки в ctor-инициализаторе конструктора (12.6.2), сохраняется до выхода конструктора. Временная связь с параметром ссылки в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.

Дополнительную информацию см. ниже:

Пример, который может помочь визуализировать происходящее:

#include <iostream>
#include <string>

class foo {
public:
    foo( std::string const& n) : name(n) { 
        std::cout << "foo ctor - " << name + " created\n"; 
    };
    foo( foo const& other) : name( other.name + " copy") { 
        std::cout << "foo copy ctor - " << name + " created\n";
    };

    ~foo() { 
        std::cout << name + " destroyed\n"; 
    };

    std::string getname() const { return name; };
    foo getcopy() const { return foo( *this); };

private:
    std::string name;
};

std::ostream& operator<<( std::ostream& strm, foo const& f) {
    strm << f.getname();
    return strm;
}


int main()
{
    foo x( "x");

    std::cout << x.getcopy() << std::endl;

    std::cout << "note that the temp has already been destroyed\n\n\n";

    foo const& ref( x.getcopy());

    std::cout << ref << std::endl;

    std::cout << "the temp won't be deleted until after this...\n\n";
    std::cout << "note that the temp has *not* been destroyed yet...\n\n";
}

Что отображает:

foo ctor - x created
foo copy ctor - x copy created
x copy
x copy destroyed
note that the temp has already been destroyed


foo copy ctor - x copy created
x copy
the temp won't be deleted until after this...

note that the temp has *not* been destroyed yet...

x copy destroyed
x destroyed
9
ответ дан 4 December 2019 в 13:00
поделиться

Обычно, если вы возвращаете объект по значению из функции, указанный объект будет уничтожен, когда выражение присваивания будет завершено:

myclass X = getX(); // after copy constructor, the returned value is destroyed
                    // (but you still hold a copy in X)

В случае, который вы описываете, возвращенное значение будет уничтожено позже, что позволит вам используйте это:

const myclass& X = getX();
cout << X.a << endl; // still can access the returned value, it's not destroyed
1
ответ дан 4 December 2019 в 13:00
поделиться

Дело в том, что при возврате по значению значение копируется в переменную, которой вы назначаете результат функции. (как вы и сказали - вызывается конструктор копирования ). Никакого продления срока службы, вы просто создаете совершенно новый объект.

При возврате по ссылке вы просто передаете указатель на переменную, определенную в функции. Итак, новый объект не создается, у вас просто есть ссылка на него вне функции. В этом случае увеличивается время жизни внутренней переменной.

2
ответ дан 4 December 2019 в 13:00
поделиться

Во-первых, время жизни временного объекта продлевается до времени жизни привязанной к нему ссылки const, а не "до области видимости вызывающей функции" (хотя, возможно, именно это вы имели в виду под странной формулировкой "область видимости вызывающей функции"). Именно это иллюстрирует ваш CASE A, где вы присоединяете const ссылку к временной. Временный объект продолжает жить до тех пор, пока живет ссылка. Когда срок жизни ссылки заканчивается, временный объект также уничтожается.

Во-вторых, ваш CASE B просто плохо сформирован, не компилируется. А именно,

BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox(); 

является незаконным. В C++ запрещено присоединять неконстантную ссылку к временной. Если ваш компилятор позволяет это, то это должно быть причуда/расширение вашего компилятора, которое имеет мало общего с языком C++.

4
ответ дан 4 December 2019 в 13:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: