shared pointer from raw pointer

Hello forum,

I have a class member function that returns the whole object as follows:


 
A B::doIt() {}


I want to create a shared pointer from the returned object as follows:

 
std::shared_ptr<A> aPtr = &doIt();


But the above code is not correct as a raw pointer cannot to be assigned to smart pointer directly. I wrote it just to give the impression what I want to achieve. Any hint to this issue ?


Thanks
> as a raw pointer cannot to be assigned to smart pointer
See http://www.cplusplus.com/reference/memory/shared_ptr/shared_ptr/ and notice that you do have a constructor that takes a raw pointer
std::shared_ptr<A> aPtr{ &doIt() };

However, note that you are trying to get the memory address of a temporary.
Let me rephrase the issue properly. I have allocated an array of memory in the heap as follows:

1
2
3

std::vector<std::shared_ptr<Triangle>> triangles_;


The above vector is initialized the with the allocated memory on the heap and then each element is sent to a function as follows:

1
2
3
4
5
6
7
8

void setFromTriangle(const Triangle &tr)
{
     std::shared_ptr<Triangle> parent ;

     parent.reset(&tr);  /// ??????
}


Is the snippet inside the function valid ?


Thanks
Is the snippet inside the function valid ?
No, the shared_ptr takes ownership of the pointer and deletes it when there are no references anymore. See:

http://www.cplusplus.com/reference/memory/shared_ptr/
Sorry I provided some wrong information . What if parent is a class member as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class Line
{
    public:
       Line(); // parent is initialized to nullptr inside the Line constructor
    private:
       std::shared_ptr<const Triangle> parent;
};


void Line::setFromTriangle(const Triangle &tr)
{
     ................................
     parent.reset(&tr);  // ?????????
 

     ..............................
     ..............................
}


All the triangles inside the vector are allocated inside the heap memory .

Is the above snippet inside the member function fine ? The parent is set to nullptr again inside the Line destructor.
Last edited on
¿does it compile?
`tr' is a const reference, `parent' points to non-const.

If you intend to use it with a shared pointer, ¿why doesn't your function ask for a shared pointer?
void Line::setFromTriangle(std::shared_ptr<Triangle> tr)
If, how, when it crashes depends entirely on the passed parameter. It is not predictable.

The only way to make a shared_ptr from the parameter (not a raw pointer) is making a copy:
1
2
3
4
5
6
7
8
9
oid Line::setFromTriangle(const Triangle &tr)
{
     ................................
     parent.reset(new Triangle(tr));  // ?????????
 

     ..............................
     ..............................
}
Which one is better option

1
2
3
4
5
6
void A::setSomething(const B&)
{
   .............
   .............
}


or

1
2
3
4
5
void A::setSomething(std::shared_ptr<const B>)
{
   .............
   .............
}


Here it is considered the fact that B is allocated on heap memory


Thanks
> Which one is better option

There are two approaches that could be taken:

One:
If the invariant (pre-condition) is that an object must be passed, pass by reference.
If the object may not be there, pass a pointer by value (nullptr if there is no object).
This is very clean; it expresses the invariant in the declaration (header), in code rather than in comments.

Two:
If the object has a dynamic storage duration, always use pointer semantics.
Otherwise, follow approach one.

Both are acceptable alternatives; pick the one that appeals to you, and then be consistent about it.

Re. the original question: See: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
Important:
Note that prior to calling shared_from_this on an object t, there must be a std::shared_ptr that owns t.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <memory>

struct triangle : std::enable_shared_from_this<triangle>
{
    static std::shared_ptr<triangle> create( /* constructor_args */ )
    { return std::shared_ptr<triangle>( new triangle( /* constructor_args */ ) ) ; }

    std::shared_ptr<triangle> pointer() { return shared_from_this(); }
    std::shared_ptr< const triangle > pointer() const
    { return const_cast<triangle*>(this)->pointer(); }

    virtual ~triangle() { std::cout << "triangle " << this << " destructor\n" ; } // for tracing what is going on
    // ...

    protected: triangle( /* constructor_args */ ) /* init */
    { /* ... */ std::cout << "triangle " << this << " constructor\n" ; } // for tracing what is going on
};

int main()
{
    auto ptr1 = triangle::create( /* constructor_args */ ) ;
    std::cout << "ptr1 points to triangle at: " << ptr1.get() << '\n' ;

    if(ptr1)
    {
        triangle& t = *ptr1 ;
        auto ptr2 = t.pointer() ;
        std::cout << "ptr2 points to triangle at: " << ptr2.get() << '\n' ;

        const triangle& ct = t ;
        std::shared_ptr<const triangle > ptr3 = ct.pointer() ;
        std::cout << "ptr3 points to triangle at: " << ptr3.get() << '\n' ;
    }

    // uncomment the code below to engender undefined behaviour
    /*
    if(ptr1)
    {
        triangle& t = *ptr1 ;
        auto ptr2 = std::shared_ptr<const triangle >( std::addressof(t) ) ;
        std::cout << "ptr2 points to triangle at: " << ptr2.get() << '\n' ;
    }
    */
}

http://coliru.stacked-crooked.com/a/d880219039795265
May have deviated a bit from the topic, but deals with the similar issue. Consider the following snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


std::shared_ptr<Vertex> v1,v2,v3;
std::shared_ptr<Normal> n;

for(unsigned int i = 0; i < triangles_.size(); ++i)
{
      ........................
      ........................
      v1 =  std::make_shared<Vertex>(val1,val2,val3);
      ........................
      ........................
      
       triangles_.push_back(std::make_shared<Triangle>(v1,v2,v3,n));
}


In the above snippet triangles_ is a class member of the following type:

 
std::vector<std::shared_ptr<Triangle>> triangles_;



Now please compare the above for loop with the following . Is there any logical difference between the two. I do not see any. If there is , then please show this blind person!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

for(unsigned int i = 0; i < triangles_.size(); ++i)
{
      ........................
      ........................
      std::shared_ptr<Vertex> v1 =  std::make_shared<Vertex>(val1,val2,val3);
      std::shared_ptr<Vertex> v2 =  std::make_shared<Vertex>(val1,val2,val3);
      std::shared_ptr<Vertex> v3 =  std::make_shared<Vertex>(val1,val2,val3);
      std::shared_ptr<Normal> n = std::make_shared<Normal>(norm1,norm2,norm3);

      ........................
      ........................
      
       triangles_.push_back(std::make_shared<Triangle>(v1,v2,v3,n));
}


Out of the for loop scope the v1,v2,v3, n are destroyed in the immediate above code snippet. Does it affect the contents of the triangles_ vector ? I guess the pointers are copied there and dynamically allocated memory remains intact as long as there is some one pointing at . Your comments will be helpful here.


Thanks
> I guess the pointers are copied there and dynamically allocated memory
> remains intact as long as there is some one pointing at

Shared pointers to an object share ownership of the object; they participate in managing the object's life-time. The pointed objects will go away only when the last shared pointer to it is destroyed.

Caveat:
The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr. Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior. http://en.cppreference.com/w/cpp/memory/shared_ptr
Topic archived. No new replies allowed.