Tomilov Anatoliy
Tomilov Anatoliy

Reputation: 16701

Destructor of referenced temporary object

Given example:

#include <iostream>

#include <cstdlib>

#define PRINT_NAME { std::cout << __PRETTY_FUNCTION__ << std::endl; }

namespace
{

struct A 
{
    A() { PRINT_NAME; }
    ~A() { PRINT_NAME; }
};

A f() { return {}; }

A b;

A && g() { return std::move(b); }

}

int
main()
{ 
    std::cout << "------------------" << std::endl;
    {
        f();
        std::cout << 1 << std::endl;
    }
    std::cout << "------------------" << std::endl;
    {
        A && a = f();
        // or A const & a = f(); as mentioned in below discussion
        std::cout << 2 << std::endl;
    }
    std::cout << "------------------" << std::endl;
    {
        A && a = g();
        std::cout << 3 << std::endl;
    }
    std::cout << "------------------" << std::endl;
    return EXIT_SUCCESS;
}

and its output (of clang 3.5.0):

(anonymous namespace)::A::A()
------------------
(anonymous namespace)::A::A()
(anonymous namespace)::A::~A()
1
------------------
(anonymous namespace)::A::A()
2
(anonymous namespace)::A::~A()
------------------
3
------------------
(anonymous namespace)::A::~A()

What is the semantic rule: an thinkable shortand of the standard's paragraphs, which compactly summarizes the difference in destructors behaviour regarding above code sample? I often faces "idiomatic rules" formulated via the "have some (non-obviously relevant) characteristic" or "have some inherent attribute" statements, e.g. "if it has a name, then it is an lvalue". Is there something similar?

Upvotes: 4

Views: 497

Answers (1)

Anton Savin
Anton Savin

Reputation: 41301

This has nothing to do with rvalue references. In fact, if you change A&& to const A& throughout the code, the behavior won't change.

Probably your confusion is caused by the name of std::move() function. It doesn't actually move anything, it just casts its argument to rvalue reference.

Don't think about destructors, think about lifetime of objects. Personally I don't know a simple rule of thumb (apart from "read the standard"), but these three rules may help you:

  1. Static objects have (basically) lifetime of the whole program.
  2. If a temporary object returned from a function is not bound to anything, it's lifetime ends when the whole expression execution finishes.
  3. If a temporary object returned from a function is bound to some reference, its lifetime is extended to a lifetime of that reference.

Upvotes: 4

Related Questions