Reputation: 21
What is the rationale behind n2439:
12.1.4 A constructor shall not be declared with a ref-qualifier.
and
12.4.2 A destructor shall not be declared with a ref-qualifier.
Assuming some class A with some costly ref counting semantics, i would write something like this, so as to be able to avoid retain/release-ing temporary objects:
struct B {
A a;
B (const& A a) & : a(retain(a)) {}
B (const& A a) && : a(a) {}
~B () & { release(a); }
~B () && { }
void do_something_with_a();
};
A a = getA();
auto b = B(a); // retain+released
b.do_something_with_a();
B(getA()).do_something_with_a(); // no retain / release
Upvotes: 2
Views: 70
Reputation: 69912
Intrusive reference counting like this is 20+ year old technology. It exists in such arcane places as COM and objective-c.
In their day these technologies were useful and helped us move forward (and a few steps back) but things have moved on. We have become wiser.
Nowadays we understand that separating the concerns of lifetime from function is a more sensible way to go. It allows decoupling of concepts, cleaner code that's easy to reason about.
This is why the standard has std::unique_ptr
and std::shared_ptr
...
...but no std::intrusive_base
or std::intrusive_ptr
.
Because these concepts are actually harmful.
Having reset our internal code-writing guidance systems so that we write nicely decoupled code, we find that we don't need to optimise constructors this way - if we want a reference to A we simply take a reference to A, if we want a copy of a shared_ptr
to it, we simply copy the shared_ptr
.
Code does what it says on the tin. There is no hidden magic. Suddenly, code with reference-counted objects can be reasoned about, we don't have to remember whether we need to release an object or not.
Welcome to the post c++11 world. It's wonderful :-)
Upvotes: 1