11

For the code below, I would like to know how to set std::shared_ptr to point the given objects in the two member functions. The Vector3 object which is allocated in the main function is not going to be deleted until the end of the program.

#include <memory>
#include <vector>

using std::vector;
using std::shared_ptr;

class Vector3
{
    // ...
};

class Face
{
    vector < shared_ptr <Vector3> > vtx;

    public:

    void addVtx (const Vector3& vt)
    {
        // vtx.push_back (); <-- how to push_back ?
    }

    void setVtx (const int v, const Vector3& vt)
    {
        if ( vtx.size() > 0 && v < vtx.size() )
        {
            // vtx[v] = &vt; <-- how to assign ?
        }
    }

};

int main ()
{
    vector <Vector3> vec (3);
    Face face;

    face.addVtx (vec[0]);
    face.setVtx (0, vec[0])

    return 0;
}
Shibli
  • 5,879
  • 13
  • 62
  • 126
  • 1
    *The Vector3 object which is allocated in the main function is not going to be deleted until the end of the program* - who is deleting it? If you pass ownership to `shared_ptr` it'll delete the object when `use_count` drops to 0. It doesn't sound like you need `shared_ptr` at all. Is this an attempt to placate someone who told you *raw pointers are evil*? – Praetorian Jun 04 '14 at 23:23
  • 1
    @Praetorian: Yes, I heard that putting raw pointers into containers is an evil action. – Shibli Jun 04 '14 at 23:25
  • Raw pointers that own resources are a bad idea. However, your use case seems to be storing pointers to objects with automatic storage duration in a container. There's nothing wrong with using raw pointers here. Also, if you are considering using a smart pointer, the first one you consider should be `unique_ptr`, not `shared_ptr`. – Praetorian Jun 04 '14 at 23:29
  • But if you have a `std::vector` of pointers of `Vector3` (the names do not help here :D), where are the original objects? Inside another `std::vector`? Maybe conceptually it would be best if you made the "indirect" `vector` a `std::vector::iterator>` – Massa Jun 04 '14 at 23:36

2 Answers2

15

There is not much point in using a shared_ptr for an automatically allocated object.

Technically you can do it, by giving the shared_ptr a deleter that doesn't do anything, and changing your vtx to be a vector of shared pointers to const vectors.

E.g. changing the declaration to

vector < shared_ptr <Vector3 const> > vtx;

and adding a pointer like this:

vtx.push_back( shared_ptr<Vector3 const>( &vt, [](Vector3 const*){} ) );

Disclaimer: untested code, not touched by a compiler.

However, unless you're going to also add pointers to vectors that need to be deleted, just use a vector of raw pointers. Or, just use a vector of vectors, and copy the in-data.


It's not a good idea to use raw pointers to hold ownership. For that use smart pointers.

But conversely, it's not a good idea to use ownership smart pointers to hold pure references to static or automatic objects. For that, use raw pointers or references.

In general. enter image description here

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

Disregarding the argument about whether using shared_ptr is a good idea or not, as explained by the accepted answer, you can use the following if you continue to use shared_ptr:

void addVtx (const Vector3& vt)
{
    vtx.push_back(std::make_shared<Vector3>(vt));
}

void setVtx (size_t v, const Vector3& vt)
{
    if ( vtx.size() > 0 && v < vtx.size() )
    {
       vtx[v] = std::make_shared<Vector3>(vt);
    }
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    One important point to be noted here is `std:make_shared` creates a copy of the object which is passed in the argument and uses that. That is the reason it works, eventhough shared pointers arent supposed to hold static addresses. If a copy is not desired, and if the pointer is used to edit the actual object, this method wont work, as the edited object will be a copy of the original object and changes wont reflect. Using a deleter which does nothing is the way to go in that case. – Harish Ganesan Oct 27 '22 at 07:04