Using C ++ generic pointer smoothing constructor with empty generic pointer

std :: shared_ptr has an alias constructor that allows the newly created shared_ptr to share state with an existing shared pointer, pointing to some other object.

I was thinking about abusing this constructor to put a pointer to some global object inside shared_ptr:

int global = 0; int main() { // because we point to global object we do not need to track its lifetime // so we use empty shared_ptr<void> as a provider of shared state std::shared_ptr<int> p(std::shared_ptr<void>(), &global); std::shared_ptr<int> pp = p; return *pp; } 

My question is: Is this legal? The code successfully works with the main compilers.

Note that I am not asking if this is good. I understand that there is a canonical way to put pointers to global objects in shared_ptr using no-op deleter. It is also a little troubling if it is legal, because one could have enforced shared_ptr, weak pointers to which always expired:

  std::shared_ptr<int> p(std::shared_ptr<void>(), &global); std::weak_ptr<int> w = p; if (p) // p is alive and well { // and w is not *w.lock(); // and here program crashes } 
+7
c ++ language-lawyer c ++ 11
source share
1 answer

As you already know, with your current solution p has use_count() zero, so weak_ptr expired. This seems to be ok according to the C ++ N4296 project:

20.8.2.2.1 shared_ptr constructors [util.smartptr.shared.const]
template shared_ptr (const shared_ptr & r, T * p) noexcept;
13 Effects: Creates an instance of shared_ptr in which p and ownership of r shares are stored.
14 Postconditions: get () == p && use_count () == r.use_count ()
15 [Note: To avoid the possibility of a dangling pointer, the user of this constructor must ensure that p remains valid, at least until the property group r is destroyed. - final note]
16 [Note. This constructor allows you to create an empty shared_ptr instance with a non-zero stored pointer. - end note]

20.8.2.2.2 shared_ptr destructor [util.smartptr.shared.dest]
~ Shared_ptr ();
1 Effects:
(1.1) - If * is empty or holding shares with another instance of shared_ptr (use_count ()> 1), there are no side effects.
(1.2) - Otherwise, if * it belongs to the object p and deleter d, d (p). (1.3) - Otherwise * the pointer p belongs to this, and delete p is called

my attention.
Instead, you can use the following: shared_ptr with use_count() one:

 std::shared_ptr<int> p(&global, [](int*){}); 

It uses an empty custom debugger.

+3
source share

All Articles