#include #include using namespace std; /* Smart pointers were a clever idea that dates back to the 90s, but were not widely used because of compatibility with other aspects of C++ (e.g. copy constructors required const references, which did not support "move semantics:" what needs to take place when resources are copied. std::unique_ptr (and to a lesser extend shared_ptr) tried to address these issues along with other additions to C++ in 2011 (e.g r-value references). This is the most sophisticated tool for memory management in C++ without an active garbage collector, but there are still many unsolved problems. In order to allow unique pointers to be effective, the programmer must commit to using them EXCLUSIVELY. But that's not easy to do. At least a real pointer is needed when a unique pointer is first created. But where would such a real pointer come from? One simple problem of memory management is to prevent the following from happening: int* f(int x) { return &x; } Because x gets popped off the stack upon return so the pointer returned won't be vaild. Does unqiue_ptr solve this problem? Apparently not: */ unique_ptr fu(int x) // this still compiles { unique_ptr px(&x); return px; // what happens to x when fu() returns? (it gets popped off of the stack) // This is NOT ANY BETTER than f(), makes it worse by being more complicated. } int main() { unique_ptr px = fu(3); unique_ptr py = fu(4); cout << *px << endl; // prints 4, not 3 cout << *py << endl; // prints 4 again, and core dumps at end of main, because // when px, py are destroyed it also tries to destroy the 3 and 4, which are // no longer there. int z[5]; z[0] = 10; unique_ptr pz(z); cout << pz[0] << endl; // Using, borrowing values after they've moved. unique_ptr pz2 = move(pz); // ownership passed to pz2. cout << pz2[0] << endl; //cout << pz[0] << endl; // compiles, gets seg. fault. how can we // use value once it's moved? WHY ISNT'T THIS A COMPILER ERROR?? // Difficulties with using C++ references (aliases) instead of extra pointers // array of unique pointers: unique_ptr UA[10]; for(int i=0;i<10;i++) UA[i] = unique_ptr(new int); // can't use extra pointer to unique_ptr, so try references. unique_ptr & borrow = UA[0]; // references can't be reassigned. borrow will ALWAYS alias UA[0]: *borrow = 2; //borrow = px; //UA[1]; // change what we're borrowing? won't compile // can only do for(auto& b:UA) *b = 99; for(auto& b:UA) cout << *b << ".."; cout << " end\n"; // Nothing that prevents programmer from making bad choices: int* pyy = py.get(); // forces the unique_ptr to "GIVE IT UP", unique_ptr* pu = &pz; //mix pointer and unique_ptr - recipe for disaster // core dumps on return because z gets deleted twice. return 0; }//main // Most importantly, this program compiled and there were no meaningful runtime // error messages except core dump or segmentation fault.