I have unique_ptr and a row pointer that the unique_ptr points to. How do I call release for unique_ptr using only row pointer rowPtr?
#include <iostream>
#include <memory>
int main()
{
std::unique_ptr<int> uniqPtr = std::make_unique<int>(2);
int* rowPtr = uniqPtr .get();
// call .release for uniqPtr using only rowPtr
return 0;
}
UPD:
I will clarify the question. I need uniqPtr to become empty using only rowPtr.
How do I call release for unique_ptr using only row pointer rowPtr?
You cannot. You can only release a unique pointer by calling the release member function on the unique pointer. You cannot use, nor do you need, the bare pointer to do that.
You don't. Raw pointers do not participate in ownership. Nor shall they.
When you call get you are explicitly saying: "I want only a raw pointer. I do not want to interfere with ownership of the managed pointer".
You can either use int *p = uniqPtr.release() to get the pointer without destroying it. p points still to a valid memory, but uniqPtr is no longer managing it.
You can also use uniqPtr.reset(nullptr) which would destroy the object and resets the unique_ptr to a nullptr. In this case ptr is no longer pointing to the object and the memory of that object has been freed.
In any case you can not use the raw pointer, managed by uniqPtr, to change the state of the unique_ptr object, because the raw pointer doesn't have any association with it, it's just managed by it.
Related
Consider my code below. My understanding of unique pointers was that only one unique pointer can be used to reference one variable or object. In my code I have more than one unique_ptr accessing the same variable.
It's obviously not the correct way to use smart pointers i know, in that the pointer should have complete ownership from creation. But still, why is this valid and not having a compilation error? Thanks.
#include <iostream>
#include <memory>
using namespace std;
int main()
{
int val = 0;
int* valPtr = &val;
unique_ptr <int> uniquePtr1(valPtr);
unique_ptr <int> uniquePtr2(valPtr);
*uniquePtr1 = 10;
*uniquePtr2 = 20;
return 0;
}
But still, why is this valid
It is not valid! It's undefined behaviour, because the destructor of std::unique_ptr will free an object with automatic storage duration.
Practically, your program tries to destroy the int object three times. First through uniquePtr2, then through uniquePtr1, and then through val itself.
and not having a compilation error?
Because such errors are not generally detectable at compile time:
unique_ptr <int> uniquePtr1(valPtr);
unique_ptr <int> uniquePtr2(function_with_runtime_input());
In this example, function_with_runtime_input() may perform a lot of complicated runtime operations which eventually return a pointer to the same object valPtr points to.
If you use std::unique_ptr correctly, then you will almost always use std::make_unique, which prevents such errors.
Just an addition to Christian Hackl's excellent answer:
std::unique_ptr was introduced to ensure RAII for pointers; this means, in opposite to raw pointers you don't have to take care about destruction yourself anymore. The whole management of the raw pointer is done by the smart pointer. Leaks caused by a forgotten delete can not happen anymore.
If a std::unique_ptr would only allow to be created by std::make_unique, it would be absolutely safe regarding allocation and deallocation, and of course that would be also detectable during compile time.
But that's not the case: std::unique_ptr is also constructible with a raw pointer. The reason is, that being able to be constructed with a hard pointer makes a std::unique_ptr much more useful. If this would not be possible, e.g. the pointer returned by Christian Hackl's function_with_runtime_input() would not be possible to integrate into a modern RAII environment, you would have to take care of destruction yourself.
Of course the downside with this is that errors like yours can happen: To forget destruction is not possible with std::unique_ptr, but erroneous multiple destructions are always possible (and impossible to track by the compiler, as C.H. already said), if you created it with a raw pointer constructor argument. Always be aware that std::unique_ptr logically takes "ownership" of the raw pointer - what means, that no one else may delete the pointer except the one std::unique_ptr itself.
As rules of thumb it can be said:
Always create a std::unique_ptr with std::make_unique if possible.
If it needs to be constructed with a raw pointer, never touch the raw pointer after creating the std::unique_ptr with it.
Always be aware, that the std::unique_ptr takes ownership of the supplied raw pointer
Only supply raw pointers to the heap. NEVER use raw pointers which point to local
stack variables (because they will be unavoidably destroyed automatically,
like valin your example).
Create a std::unique_ptr only with raw pointers, which were created by new, if possible.
If the std::unique_ptr needs to be constructed with a raw pointer, which was created by something else than new, add a custom deleter to the std::unique_ptr, which matches the hard pointer creator. An example are image pointers in the (C based) FreeImage library, which always have to be destroyed by FreeImage_Unload()
Some examples to these rules:
// Safe
std::unique_ptr<int> p = std::make_unique<int>();
// Safe, but not advisable. No accessible raw pointer exists, but should use make_unique.
std::unique_ptr<int> p(new int());
// Handle with care. No accessible raw pointer exists, but it has to be sure
// that function_with_runtime_input() allocates the raw pointer with 'new'
std::unique_ptr<int> p( function_with_runtime_input() );
// Safe. No accessible raw pointer exists,
// the raw pointer is created by a library, and has a custom
// deleter to match the library's requirements
struct FreeImageDeleter {
void operator() (FIBITMAP* _moribund) { FreeImage_Unload(_moribund); }
};
std::unique_ptr<FIBITMAP,FreeImageDeleter> p( FreeImage_Load(...) );
// Dangerous. Your class method gets a raw pointer
// as a parameter. It can not control what happens
// with this raw pointer after the call to MyClass::setMySomething()
// - if the caller deletes it, your'e lost.
void MyClass::setMySomething( MySomething* something ) {
// m_mySomethingP is a member std::unique_ptr<Something>
m_mySomethingP = std::move( std::unique_ptr<Something>( something ));
}
// Dangerous. A raw pointer variable exists, which might be erroneously
// deleted multiple times or assigned to a std::unique_ptr multiple times.
// Don't touch iPtr after these lines!
int* iPtr = new int();
std::unique_ptr<int> p(iPtr);
// Wrong (Undefined behaviour) and a direct consequence of the dangerous declaration above.
// A raw pointer is assigned to a std::unique_ptr<int> twice, which means
// that it will be attempted to delete it twice.
// This couldn't have happened if iPtr wouldn't have existed in the first
// place, like shown in the 'safe' examples.
int* iPtr = new int();
std::unique_ptr<int> p(iPtr);
std::unique_ptr<int> p2(iPtr);
// Wrong. (Undefined behaviour)
// An unique pointer gets assigned a raw pointer to a stack variable.
// Erroneous double destruction is the consequence
int val;
int* valPtr = &val;
std::unique_ptr<int> p(valPtr);
This example of code is a bit artificial. unique_ptr is not usually initialized this way in real world code. Use std::make_unique or initialize unique_ptr without storing raw pointer in a variable:
unique_ptr <int> uniquePtr2(new int);
I accidentally found this issue on C++, but totally had no idea how it was happened, please check the code snippet below:
int main() {
int *aptr = new int(20); //Declare an integer space with 20, and aptr points to it
shared_ptr<int> a(aptr); //Declare a shared_ptr to points where aptr points
stringstream ss;
ss << a;
const char *chstr = ss.str().c_str(); // Save the address as string
void *address;
sscanf(chstr, "%p", (void **)&address); // Convert string back to pointer
a = NULL; // Free the shared pointer
cout << *reinterpret_cast<int*>(address) << endl; // Output: 0, 20 has gone
return 0;
}
Is there anybody could tell me why the address has been freed ?
I didn't manipulate the original integer pointer "aptr", but somehow it's space has disappeared, because of the shared_ptr ?
I'd like to know how it was happend, thank you all !
The whole purpose behind std::shared_ptr is to take ownership of the dynamically-allocated object. Once std::shared_ptr takes ownership of a dynamically-allocated object, via either std::make_shared or by directly assigning a pointer to it, std::shared_ptr owns it, lock stock and barrel. Owning it means automatically deleteing the dynamically scoped object when the last reference to the dynamically-scoped object goes out of scope. That's what the shared_ptr is for, and nothing else.
a = NULL;
This used shared_ptr's assignment operator to replace the shared_ptr-owned pointer(*). Since the original dynamically-scoped object that the shared_ptr owns has no other reference, the shared_ptr deletes the original pointer that was used to construct it.
The fact that you still have the original, native pointer to the int is irrelevant. shared_ptr doesn't care. The whole thing gets deleted.
If you don't want shared_ptr to delete whatever you newed, and use a native pointer for, either don't use shared_ptr, or make sure one is still around as long as you still need to use a native pointer to the underlying object.
(*) This actually implicitly constructs another shared_ptr, and uses the regular assignment operator.
This code does not compile in g++ 4.2.1 (but as Sam mentioned, it complies with version 6):
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
main.cpp:17:11: error: no viable overloaded '='
a = NULL; // Free the shared pointer
~ ^ ~~~~
By the way, you should use shared_ptr::reset:
In all other cases, the shared_ptr acquires ownership of p with a use
count of 1, and -optionally- with del and/or alloc as deleter and
allocator, respectively.
Additionally, a call to this function has the same side effects as if
shared_ptr's destructor was called before its value changed (including
the deletion of the managed object if this shared_ptr was unique).
Also check string::c_str. You are saving the address of a temporary string, which is the start of something bad.
I wanted to ask like we can do with a pointer.
int q = 10;
int* p = &q;
How to do something with a shared_ptr? Can I use make_shared<> here?
shared_ptr<int> r = make_shared<int>(q);
Is this correct?
If you want a shared_ptr that owns a pointer, use the constructor directly:
std::shared_ptr<int> r(some_pointer_to_int);
If you want a shared_ptr that points to a copy of a given object, use make_shared:
auto r = std::make_shared<int>(some_int);
Note that the former would NOT be correct if the pointer points to an object with automatic storage duration. Such objects are managed by the runtime.
No it is not. Smart pointer is here for guaranteed deletion of the pointer(handle) around which it wraps. In your example you just take address of the local stack variable. Deletion of such a variable is undefined behavior(your app will crash most of the time).
But if your actual code is different and you truly want to keep an existing pointer(which is ok to delete later) in the shared_ptr you should do the following:
shared_ptr<int> r{q};
make_shared exists as a helper for creating shared_ptr passing arguments to the object the pointer is going to point to.
The point of smart pointers is to maintain their memory smartly. In your case q is located on the stack. If you pass it to a smart pointer then it will get deleted when it is no longer referenced. This will crash your program because you can't delete memory on the stack. It is also sort of silly to want to because it is freed when q goes out of scope anyway.
make_shared<>() takes the arguments to a constructor.
shared_ptr<int> r = make_shared<int>(q);
This constructs a shared point to a single int that holds the same value as q.
If you want to assign a pointer to a shared pointer you would do something like:
shared_ptr<int> r = q;
That being said, your particular example makes no sense. When the shared pointer goes out of scope it will call delete on a stack allocated variable with invokes undefined behavior.
Without any usage information it depends upon the lifetime. If you only need to use it during a function, you're better off with a reference.
auto& r = *q;
If you must get a pointer type you can do
auto& r = q;
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.
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.
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).
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.
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);
I try to understand how std::unique_ptr works and for that I found this document. The author starts from the following example:
#include <utility> //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();
What is confusing to me is that in this line
unique_ptr<int> uptr (new int(3));
We use integer as an argument (between round brackets) and here
unique_ptr<double> uptr2 (pd);
we used an pointer as an argument. Does it make any difference?
What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.
The constructor of unique_ptr<T> accepts a raw pointer to an object of type T (so, it accepts a T*).
In the first example:
unique_ptr<int> uptr (new int(3));
The pointer is the result of a new expression, while in the second example:
unique_ptr<double> uptr2 (pd);
The pointer is stored in the pd variable.
Conceptually, nothing changes (you are constructing a unique_ptr from a raw pointer), but the second approach is potentially more dangerous, since it would allow you, for instance, to do:
unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);
Thus having two unique pointers that effectively encapsulate the same object (thus violating the semantics of a unique pointer).
This is why the first form for creating a unique pointer is better, when possible. Notice, that in C++14 we will be able to do:
unique_ptr<int> p = make_unique<int>(42);
Which is both clearer and safer. Now concerning this doubt of yours:
What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.
Smart pointers are supposed to model object ownership, and automatically take care of destroying the pointed object when the last (smart, owning) pointer to that object falls out of scope.
This way you do not have to remember doing delete on objects allocated dynamically - the destructor of the smart pointer will do that for you - nor to worry about whether you won't dereference a (dangling) pointer to an object that has been destroyed already:
{
unique_ptr<int> p = make_unique<int>(42);
// Going out of scope...
}
// I did not leak my integer here! The destructor of unique_ptr called delete
Now unique_ptr is a smart pointer that models unique ownership, meaning that at any time in your program there shall be only one (owning) pointer to the pointed object - that's why unique_ptr is non-copyable.
As long as you use smart pointers in a way that does not break the implicit contract they require you to comply with, you will have the guarantee that no memory will be leaked, and the proper ownership policy for your object will be enforced. Raw pointers do not give you this guarantee.
There is no difference in working in both the concepts of assignment to unique_ptr.
int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);
is similar to
unique_ptr<int> uptr (new int(3));
Here unique_ptr automatically deletes the space occupied by uptr.
how pointers, declared in this way will be different from the pointers declared in a "normal" way.
If you create an integer in heap space (using new keyword or malloc), then you will have to clear that memory on your own (using delete or free respectively).
In the below code,
int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;
Here, you will have to delete heapInt, when it is done using. If it is not deleted, then memory leakage occurs.
In order to avoid such memory leaks unique_ptr is used, where unique_ptr automatically deletes the space occupied by heapInt when it goes out of scope. So, you need not do delete or free for unique_ptr.
Unique pointers are guaranteed to destroy the object they manage when they go out of scope.
http://en.cppreference.com/w/cpp/memory/unique_ptr
In this case:
unique_ptr<double> uptr2 (pd);
pd will be destroyed when uptr2 goes out of scope. This facilitates memory management by automatic deletion.
The case of unique_ptr<int> uptr (new int(3)); is not different, except that the raw pointer is not assigned to any variable here.
From cppreference, one of the std::unique_ptr constructors is
explicit unique_ptr( pointer p ) noexcept;
So to create a new std::unique_ptr is to pass a pointer to its constructor.
unique_ptr<int> uptr (new int(3));
Or it is the same as
int *int_ptr = new int(3);
std::unique_ptr<int> uptr (int_ptr);
The different is you don't have to clean up after using it. If you don't use std::unique_ptr (smart pointer), you will have to delete it like this
delete int_ptr;
when you no longer need it or it will cause a memory leak.