int main() { std::cout << "start test1" << std::endl; foo* f = new foo(); std::unique_ptr<foo> uptr1(f);
// std::cout << "start test2" << std::endl; // std::unique_ptr<foo> uptr2(f); // there is sig fault if the delete will be called twice for the unique ptr
//////output////// start test1 foo constructor is called start test3 foo constructor is called start test4 foo constructor is called foo constructor is called foo move constructor is called foo destructor is called start test5 foo constructor is called finish tests foo destructor is called foo destructor is called foo destructor is called foo destructor is called
let’s analyse the related test cases,
For the test1, we use new to allocate the memory and then use this pointer to init the unique pointer.
For test2, we let the two unique pointer to point to the same raw pointer, this will cause the memory problem, since the delete function is called twice.
For test3, there is not much differences compared with the test1
For test4, we use the make_unique, if the parameters of the make unique is an class instance, the move constructor is called and the original class will be deleted. and the object is constructed twice according to the log, it shows that the unique ptr create an copy for the original object and delete the original one.
For the test5, which is also the prefered approach for init the unique pointer compared with the new operation, the default constructor is only called once and the created object is managed by the unique pointer. refer to the item21 for the effective modern cpp for more details.
If we try to copy the unique pointer by this:
1
std::unique_ptr<foo> uptr6 = uptr5;
there is error message like this:
1
error: call to implicitly-deleted copy constructor of 'std::unique_ptr<foo>'
since the unique pointer is exclusive and the copy constructor of this class is deleted, the compiler does not allow us to execute the copy operation for the unique ptr.
copy the contents pointed by raw data into the shared pointer space
There are two solutions,
first is to reset the shared pointer to the memory space where raw pointer pointed to, use the reset function of the shared pointer. refer to this. In this case, there is only one memory space.
second is that the shared pointer will point to the new allocated space, and it will get data from the raw space, the std::copy function could be used in this case, copy data from the source to the destination.
1
std::copy(rpt,rpt+elemSize,sharedPtr.get())
when the destructor will be called
The destructor of the shared pointer will be called when there is no reference bind with the memory space.
// function that calls the delete [] on received pointer void deleter(Sample * x) { std::cout << "DELETER FUNCTION CALLED\n"; delete[] x; }
std::shared_ptr<Sample> g;
void testShare(){ // Creating a shared+ptr with custom deleter std::shared_ptr<Sample> p3(new Sample[3], deleter); g=p3; return; } int main() { testShare();
std::cout<<"ok for executing test share" <<std::endl; std::cout<<"do sth else" <<std::endl; sleep(2); return 0; }
destructor will be called after the testShare(); if there is no shared pointer in global domain, the object will be release after testShare() function.
If we use the same object to test the shred ptr, there are following outputs:
int main() { std::cout << "start test1" << std::endl; foo* f = new foo(); std::shared_ptr<foo> uptr1(f);
std::cout << "start test2" << std::endl; //this case is not ok //std::shared_ptr<foo> uptr2(f); //this case is ok std::shared_ptr<foo> uptr2 = uptr1; // there is sig fault if the delete will be called twice for the unique ptr
//////output////// start test1 foo constructor is called start test2 start test3 foo constructor is called start test4 foo constructor is called foo constructor is called foo move constructor is called foo destructor is called start test5 foo constructor is called start test6 finish tests foo destructor is called foo destructor is called foo destructor is called foo destructor is called
we could see that it is ok to copy the shared pointer back and forth between each other, but we could not init two shared pointer based on one raw pointer. if we use the following operation for the test2:
1
std::shared_ptr<foo> uptr2(f);
there is also memory problem such as:
1
pointer being freed was not allocated
since the new shared pointer does not know that this pointer have managed by the the other raw pointer. The workable way is just copy the shared pointer between each other if it is needed by other classes or function such as this way:
1
std::shared_ptr<foo> uptr2 = uptr1;
instead of creating a new shared pointer based on the same raw pointer.