struct S{}; void f(const S& value){} f(S());
f()
. Why pretty accurate? - Because, in the case of q(A(), B());
The order of creation and, accordingly, the destruction of objects A and B is not defined. Everyone knows that it is impossible to write int& r = 1; //
const int& r = 1;
In this case, according to the standard and Stroustrup (7.7.1) struct Obj { Obj(int i) : m_i(i) { cout << "ctr: " << m_i << endl; } ~Obj() { cout << "dtr: " << m_i << endl; } Obj operator+(const Obj& value) { return Obj(m_i + value.m_i); } int m_i; }; ... Obj o1(1); const Obj& ro2 = Obj(2) + Obj(3); Obj o6(6);
Obj(2)
and Obj(3)
(the sequence is not defined by the standard)ro2
initializedObj(2)
and Obj(3)
collapseo6
will be createdo5
,
and o1
ctr: 1 ctr: 3 ctr: 2 ctr: 5 dtr: 2 dtr: 3 ctr: 6 dtr: 6 dtr: 5 dtr: 1
Obj
and add struct D : Obj { D(int i) : Obj(i) { cout << "D::ctr: " << m_i << endl; } ~D() { cout << "D::dtr: " << m_i << endl; } }; Obj o1(1); const Obj& ro2 = D(5); Obj o6(6);
Conclusion: ctr: 1 ctr: 5 D::ctr: 5 ctr: 6 dtr: 6 D::dtr: 5 dtr: 5 dtr: 1
Those. in this case, despite the fact that the type of the constant reference is const Obj&
, nevertheless, our object D
“lives” while “lives” a link to it.ScopeGuard
approach ( http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2 ). I personally would not use such an approach and would wrap the necessary resource handle into the class with the appropriate destructor and designer. const Obj& f() {return Obj();}
the temporary object will collapse before exiting the function, and the returned reference will be a bat. The lifetime of an object is determined only by a local reference. It will be harder to say more concise and clearer than the standard; if it is interesting, then start with paragraph 12.2. Here is a quotation from the standard (which quite often meets in all sorts of bagzillah and forums):The second context is when a reference is bound to a temporary. There are no limits on the number of people who are living there. A constructor's reference to the constructor (12.6.2). A callback (5.2.2) is given in the function call.
#include <iostream> struct foo { ~foo() { std::cout << "~foo()\n"; } }; struct foo_holder { const foo &f; }; int main() { foo_holder holder = { foo() }; std::cout << "done!\n"; return 0; }
I would suggest that the conclusion should be ~foo() done!
~foo() done! ~foo()
And (g ++ (Ubuntu / Linaro 4.7.3-1ubuntu1) 4.7.3): done! ~foo()
Source: https://habr.com/ru/post/186790/
All Articles