Question

I am just learning about smart pointers, and I am having trouble assigning a pre-existing location of a variable to the standard library's shared pointer.

For example, lets say you have an int x, which you do not know the value of. With normal pointers, I just did

int* ptr;
ptr = &x;

I tried both that with shared pointers, and

std::tr1::shared_ptr<int> ptr;
ptr = std::make_shared<int> (&x)

So i'm fairly lost as to how to do it.

Was it helpful?

Solution

You wouldn't (usually) make a smart pointer point to an existing variable. A smart pointer manages the lifetime of a dynamically allocated object, deleting it after use; pointing it to something that wasn't dynamically allocated will cause an error if it tries to delete it.

You would usually use new or make_shared to create an object, and create or assign a smart pointer with the result of that:

std::shared_ptr<int> ptr(new int(42)); // Create a new pointer to manage an object
ptr.reset(new int(66));                // Reset to manage a different object
ptr = std::make_shared<int>(53);       // Use `make_shared` rather than `new`

make_shared is usually preferable to new, since it makes better use of memory and gives stronger exception-safety.

OTHER TIPS

Shared pointers are used to manage dynamically allocated memory and more precisely, they manage the ownership for this memory.

Basically, a smart pointer is a materialization of the Ressource Acquisition Is Initialization, or RAII. I strongly suggest you take a look at this principle, as it is extremely useful for managing resource ownership (basically, each time you need to acquire a resource, and release it, be it memory, a database connection, a file handler, a mutex, etc.).

What it does is basically guarantee that while someone points at the dynamically allocated memory it manages, then this memory will be available, and as soon as the last (smart) pointer to this memory goes out of scope, then delete is called.

Then, it makes no sense to use smart pointers with variable that have automatic storage duration (i.e. that are removed when they go out of scope or when the object they're member of goes itself out of scope or is deleted (if it was new'd).

as soon as the reference counter of the shared_ptr reaches zero, the object will be deleted by the last shared_ptr. with smart pointers you can specify the function which shall delete that object.

the Deleter is a simple function (defaults to the usual operator delete) that has to be bound to the smart pointer, either statically via template parameter (see unique_ptr) or dynamically via constructor parameter (see shared_ptr).

// dynamically via shared_ptr:
//   shared_ptrs share the pointer to the Deleter
//   because they already share a common data structure for reference counting.
auto ignore = [](int* o){
    std::cout<<"i will refuse to delete this object: " << o << "\n";
    std::cout<<"not my responsibility." <<std::endl;
};
std::shared_ptr<int> sptr(&x,ignore);


//statically via unique_ptr:
//  actually, the unique_ptr is as data structure not more than a regular pointer.
//  but a pointer with special copy-constructor and destructor,
//  which will most likely be inlined.
//  there is no space to store a reference to a Deleter dynamically.
struct IgnorantDeleter{
    void operator()(int* o){
        std::cout<<"who ate my cake? " << o << "\n";
        std::cout<<"but i baked it." <<std::endl;
    }
};
std::unique_ptr<int,IgnorantDeleter> uptr(&x);

You should not create a smart pointer pointing to an object that is not dynamically allocated. Otherwise the smart pointer may try to delete the allocated memory which in turn will cause an error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top