void scrollpane::add_widget(widget* w, int x, int y, int z_order) { if (w == NULL) return; widget_map::iterator itor = std::find_if(content_.begin(), content_.end(), widget_finder(w)); if (itor != content_.end()) return; scrollpane_widget spw(w, x, y, z_order); w->set_clip_rect(client_area()); content_.insert(std::pair<int, scrollpane_widget>(z_order, spw)); position_widget(spw); // Recalculates the whole content size update_content_size(); }
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 }
int main() { /* For std::unique_ptr, the type of the deleter is part of the type of the * smart pointer. For std::shared_ptr, it's not. */ std::cout << "Part 1: deleter type being part or not" << std::endl; std::unique_ptr< // deleter type is Widget, decltype(loggingDel) // part of ptr type > upw(new Widget, loggingDel); std::shared_ptr<Widget> // deleter type is not spw(new Widget, loggingDel); // part of ptr type /* The std::shared_ptr design is more flexible: the type of the custom deleter * is not part of the shared_ptr type, so the following things are for example * possible: * * -> can be placed in containers of objects of the shared_ptr type * -> they can be assigned to one another * -> they can be passed to a function taking a parameter of * type std::shared_ptr<Widget>. * -> ... * * None of these things can be done with std::unique_ptrs that differ in the * types of their custom deleters, because the type of the custom deleter would * affect the type of the std::unique_ptr. */ std::cout << "Part 2: std::shared_ptr design being more flexible" << std::endl; auto customDeleter1 = [](Widget *pw) { makeLogentry(pw); delete pw; }; // custom deleters, auto customDeleter2 = [](Widget *pw) { makeLogentry(pw); delete pw; }; // each with a // different type std::shared_ptr<Widget> pw1(new Widget, customDeleter1); std::shared_ptr<Widget> pw2(new Widget, customDeleter2); std::vector<std::shared_ptr<Widget>> vpw { pw1, pw2 }; /* * BAD BAD BAD: constructing more than one std::shared_ptr from a single * raw pointer results in undefined behavior. */ std::cout << "Part 3: std::shared_ptr construction error" << std::endl; //auto pw = new Widget; // //std::shared_ptr<Widget> spw1(pw, loggingDel); // create control // // block for *pw // //std::shared_ptr<Widget> spw2(pw, loggingDel); // create 2nd // // control block // // for *pw! std::shared_ptr<Widget> spw1(new Widget, // direct use of new loggingDel); std::shared_ptr<Widget> spw2(spw1); // spw2 uses same // control block as spw1 std::cout << "Part 4: right before end of main" << std::endl; }