-1

Can anybody explain how "self_( this, []( ... ) {} )" works?

struct Parent {
    std::shared_ptr<Parent> self_;
    Parent() : self_( this, []( ... ) {} ) {}
    operator std::shared_ptr<Parent>() const { return self_; }
}
max66
  • 65,235
  • 10
  • 71
  • 111
SyCoDeR
  • 23
  • 4
  • 3
    It doesn't - you're passing in a no-op deleter, so you might as well just use a raw pointer. – rustyx Aug 23 '19 at 22:11
  • It works somehow, and corretly fill _self (this sample [from here](https://stackoverflow.com/a/53750202/3172339)) But i don't understand, what ", []( ... ) {}" do... – SyCoDeR Aug 23 '19 at 22:15
  • That operator should not return a shared_ptr it should return a weak_ponter. If the object is deleted now while other shared pointers exist then these shared pointers will be pointing at a deleted object. – Martin York Aug 23 '19 at 22:55
  • Do note that `self_` (nor any locked weak ptr thereof) will not keep `this` alive. Even if `this` is managed by a shared pointer they will have different management blocks. This is a very dangerous design choice... – Cruz Jean Aug 24 '19 at 02:46
  • This whole design makes no sense. What is the point of a class saving a pointer to itself? At the very least, the class should derive from [`std::enable_shared_from_this`](https://en.cppreference.com/w/cpp/memory/enable_shared_from_this) and then use [`shared_from_this()`]() to create external `shared_ptr` objects for itself. But not for one internal to itself – Remy Lebeau Aug 24 '19 at 04:02

2 Answers2

4

Can anybody explain how "self_( this, []( ... ) {} )" works?

self_, member of Parent, is a std::shared_ptr<Parent>.

With

self_( this, []( ... ) {} )

is initialized using a constructor with two arguments:

(1) the pointer shared, this, a pointer to the same object containing self_ (so the name)

(2) the function that is called when the self_ object is deleted

Observe the function: []( ... ) {}

It's a lambda function that can accept all (..., the old-C variadic way) and do nothing (the body is empty).

This (the do-nothing deleter) is done because when the last shared pointer with a specific value is destroyed, nothing has to be done over a this pointer.

max66
  • 65,235
  • 10
  • 71
  • 111
  • Thanks for your answer. It is become much more clear now. But, one question left - why this "delete" lambda is required (even it does nothing)? (without it code compiled but produce runtime error) – SyCoDeR Aug 23 '19 at 22:20
  • 2
    @SyCoDeR - think about a shared pointer: usually is an allocated (`new`) value that is shared between different objects. So, usually, when an object is destroyed, the destructor do nothing until there is another shared pointer with the same value and delete (`delete` operator) the pointer contained deleting the last shared pointer. In this case we don't want that the value, `this`, is deleted by the last shared pointer destructor. – max66 Aug 23 '19 at 22:24
  • Yes, i understand the trick now. Even this is shared ptr it is used only for weak ptr init. Therefore, we have no other shareds, but only self. And, without this empty deleter we will have double-destruction... Thank you! – SyCoDeR Aug 23 '19 at 22:29
1
[]( ... ) {}

This is nothing but lambda function, it has the following format

[ capture clause ] (parameters) -> return-type
{
definition of method
}

Capture clause: which specifies which variables are captures and captured by value or reference

Parameters: Input parameter list it can be (int val1,int val2) or (...) or anything this is just for an example

Return type: return type of lambda expression

[] : Empty capture clause means it captures nothing

(...) : variadic function

{} : Lambda body where it has code for lambda function

ChauhanTs
  • 439
  • 3
  • 6