int _tmain() { std::cout << "1. Not exception safe:" << std::endl; try { processWidget(priority(), std::shared_ptr<Widget>(new Widget())); } catch (std::exception &) {} std::cout << "2. Is exception safe:" << std::endl; try { std::shared_ptr<Widget> widget(new Widget()); processWidget(priority(), widget); } catch (std::exception &) {} std::cout << "3. Also exception safe:" << std::endl; try { processWidget(priority(), std::make_shared<Widget>()); } catch (std::exception &) {} // No std::make_unique until C++14 :-( }
int main() { // Limitation 1: none of the make functions permit the specification of custom deleters. auto widgetDeleter = [](Widget* pw) { /* ... */ }; std::unique_ptr<Widget, decltype(widgetDeleter)> upw(new Widget(), widgetDeleter); std::shared_ptr<Widget> spw(new Widget(), widgetDeleter); // Limitation 2: within the make function, the perfect forwarding code uses // parentheses, not braces. The bad news of this is that if you want to // construct your pointed-to object using a braced initializer, you must use // new directly. { auto upv = std::make_unique<std::vector<int>>(10,20); auto spv = std::make_shared<std::vector<int>>(10,20); } { // create std::initializer_list auto initList = {10, 20}; // create std::vector using std::initializer_list ctor auto spv = std::make_shared<std::vector<int>>(initList); } // Limitation 3 (only for make_shared) auto pBigObj = // create very large std::make_shared<ReallyBigType>(); // object via // std::make_shared // create std::shared_ptrs and std::weak_ptrs to // large object, use them to work with it // final std::shared_ptr to object destroyed here, // but std::weak_ptrs to it remain // during this period, memory formerly occupied // by large object remains allocated // final std::weak_ptr to object destroyed here; // memory for control block and object is released std::shared_ptr<ReallyBigType> pBigObj(new ReallyBigType); // create very large // object via new // as before, create std::shared_ptrs and // std::weak_ptrs to object, use them with it // final std::shared_ptr to object destroyed here, // but std::weak_ptrs to it remain // memory for object is deallocated // during this period, only memory for // the control block remains allocated // final std::weak_ptr to object destroyed here; // memory for control block and object is released // Exception-unsafe call processWidget( // as before std::shared_ptr<Widget>(new Widget, cusDel), // potential computePriority() // resource ); // leak! // Exception-safe calls std::shared_ptr<Widget> spw(new Widget, cusDel); processWidget(spw, computePriority()); // correct, but not // optimal; see below processWidget(std::move(spw), // both efficient and computePriority()); // exception safe }