O''''Reilly Network For Information About''''s Book part 44 pptx

6 279 0
O''''Reilly Network For Information About''''s Book part 44 pptx

Đang tải... (xem toàn văn)

Thông tin tài liệu

weak_ptr_unary(std::equal_to<string>(),string("of using"))); if (it!=vec.end()) { shared_ptr<string> sp(*++it); std::cout << *sp << '\n'; } } In the example, a vector containing weak_ptrs is created. The most interesting line of code (yes, it's quite a long one) is where we create a weak_ptr_unary_t for use with the find_if algorithm. vector<weak_ptr<string> >::iterator it=std::find_if( vec.begin(), vec.end(), weak_ptr_unary( std::equal_to<string>(),string("of using"))); The function object is created by passing another function object, std::equal_to, to the helper function weak_ptr_unary, together with the string that is to be used for the matching. Because of the fact that weak_ptr_unary_t is compatible with adaptors (it is compatible because it inherits from std::unary_function), we could compose any type of function object out of it. For instance, we could have searched for the first string not matching "of using": vector<weak_ptr<string> >::iterator it=std::find_if( vec.begin(), vec.end(), std::not1( weak_ptr_unary( std::equal_to<string>(),string("of using")))); The Boost smart pointers were specifically designed to work well with the Standard Library. That makes it easy for us to create useful components that help us simplify the usage of these powerful smart pointers. Utilities such as weak_ptr_unary aren't needed all that often; there are libraries that provide general binders that do a much better job of that than weak_ptr_unary. [15] These, too, are typically aware of smart pointer semantics, which makes using them completely transparent to use. Two Idiomatic Ways of Creating a shared_ptr from a weak_ptr As you have seen, when you have a weak_ptr that's observing some resource, you'll eventually want to access that resource. To do so, the weak_ptr must be converted to a shared_ptr, because the weak_ptr alone does not allow direct access to the resource. There are two ways of creating a shared_ptr from a weak_ptr: Either pass the weak_ptr to the constructor of shared_ptr or call the weak_ptr member function lock, which returns a shared_ptr. Which to choose depends on whether you consider an empty weak_ptr to be an error or not. The shared_ptr constructor accepting a weak_ptr argument will throw an exception of type bad_weak_ptr if the weak_ptr is empty. It should therefore be used only if an empty weak_ptr constitutes an error. When using the weak_ptr function lock, the returned shared_ptr will be empty if the weak_ptr is empty. This is the right thing to do if you need to test for a valid resourcethat is, an empty weak_ptr is expected behavior. Furthermore, when using lock , the idiomatic way to use the resource is to initialize it and test it simultaneously, like so: #include <iostream> #include <string> #include "boost/shared_ptr.hpp" #include "boost/weak_ptr.hpp" int main() { boost::shared_ptr<std::string> sp(new std::string("Some resource")); boost::weak_ptr<std::string> wp(sp); // if (boost::shared_ptr<std::string> p=wp.lock()) std::cout << "Got it: " << *p << '\n'; else std::cout << "Nah, the shared_ptr is empty\n"; } As you can see, the shared_ptr p is initialized with the result of locking the weak_ptr wp. Then p is tested, and only if it is non-empty is the resource accessed. As the shared_ptr is only valid in that scope, there is no chance of inadvertently trying to use it outside of the scope where it is valid. The other scenario is when the weak_ptr logically must be non-empty. In that case, testing for an empty shared_ptr is easy to forgetand because the shared_ptr constructor throws an exception when handed an empty weak_ptr, this is the way to go. #include <iostream> #include <string> #include "boost/shared_ptr.hpp" #include "boost/weak_ptr.hpp" void access_the_resource(boost::weak_ptr<std::string> wp) { boost::shared_ptr<std::string> sp(wp); std::cout << *sp << '\n'; } int main() { boost::shared_ptr<std::string> sp(new std::string("Some resource")); boost::weak_ptr<std::string> wp(sp); // access_the_resource(wp); } In this example, the function access_the_resource constructs the shared_ptr sp from a weak_ptr. It doesn't need to test whether the shared_ptr is empty or not, because if the weak_ptr is empty, an exception of type bad_weak_ptr is thrown, and therefore the function leaves scope immediately; catching and handling the error will be handled where it's suitable. This is much better than explicitly testing for an empty shared_ptr and then returning. These are the two ways in which to get a shared_ptr out of a weak_ptr. Summary weak_ptr is the last piece that we must place on the Boost smart pointer puzzle. The weak_ptr abstraction is a very important companion to that of shared_ptr. It allows us to break cyclic dependencies. It also handles a very common problemthat of the dangling pointer. When sharing a resource, it is common that some of the users of that resource must not take part in its lifetime management. This cannot be handled using raw pointers, because when the last shared_ptr is destroyed, it takes the shared resource with it. Had raw pointers been used to refer to that resource, there would be no way of knowing whether the resource still exists. If it doesn't, accessing it wreaks havoc. With weak_ptrs, the information that the shared resource has been destroyed is propagated to all weak_ptrs observing it, which means that no one can inadvertently access an invalid pointer. It's like a special case of the Observer pattern; when the resource is destroyed, those who have expressed interest in knowing about it are informed. Use weak_ptr to  Break cyclic dependencies  Use a shared resource without sharing ownership  Avoid dangling pointers Smart_ptr Summary This chapter has introduced the Boost smart pointers, a contribution to the C++ community that can hardly be overestimated. For a smart pointer library to be successful, it must take into consideration and correctly handle a great number of factors. I'm sure you have seen quite a number of smart pointers, and you might have even been involved in their creation, so you are aware of the effort involved to get things right. Not many smart pointers are as smart as they should be, and that makes the value of a proven library such as Boost.Smart_ptr immense. Being such a central component of software engineering, the smart pointers in Boost have obviously received a lot of attention and thorough review. It is therefore hard to give credit to all who deserve it. Many have contributed valuable opinions and have been part of shaping the current smart pointer library. However, a few exceptional people and efforts must be mentioned here:  Greg Colvin, the father of auto_ptr, also suggested counted_ptr, which later became what we now call shared_ptr.  Beman Dawes revived the discussion about smart pointers and proposed that the original semantics as suggested by Greg Colvin be considered.  Peter Dimov redesigned the smart pointer classes, adding thread safety, intrusive_ptr, and weak_ptr. It is intriguing that such a well-known concept continues to evolve. There will undoubtedly be more progress in the domain of smart pointers or maybe, smart resources, but just as important is the quality of smart pointers that are used today. It's survival of the fittest, and that's why people are using Smart_ptr. The Boost smart pointers are a fine, assorted selection of delicious software chocolate, and I eat them regularly (you should, too). We'll soon see some of them become part of the C++ Standard Library, as they have been accepted into the Library Technical Report. Endnotes 15. Boost.Bind is just such a library. How Does the Conversion Library Improve Your Programs?  Understandable, maintainable, and consistent polymorphic conversions  Static downcasting using safer constructs than static_cast  Range-preserving numeric conversions that ensure correct value logic and less time debugging  Correct and reusable lexical conversions that lead to less time coding The versatility of C++ is one of the primary reasons for its success, but sometimes also a formidable source of headaches because of the complexity of certain parts of the language. For instance, the rules for numeric conversions and type promotions are far from trivial. Other conversions are trivial, but tedious; how many times do we need to write a safe function [1] for converting between strings and ints, doubles and strings, and so on? Conversions can be problematic in every library and program you write, and that's how and why the Conversion library can help. It provides facilities that prevent dangerous conversions and simplify recurring conversion tasks. [1] To avoid using sprintf and its ilk. The Conversion library consists of four cast functions that provide better type safety (polymorphic_cast), better efficiency with preserved type safety (polymorphic_downcast), range-checked numeric conversions (numeric_cast), and lexical conversions (lexical_cast). These cast-like functions share the semantics of the C++ cast operators. Like the C++ cast operators, these functions have an important quality that, together with type safety, sets them apart from C- style casts: They unambiguously state the programmer's intent. [2] The importance of the code we write goes far further than its implementation and present behavior. More important is to clearly convey our intents when writing it. This library makes it somewhat easier by extending our C++ vocabulary. [2] They can also be overloaded, which sometimes makes them superior to the C++ cast operators. . the primary reasons for its success, but sometimes also a formidable source of headaches because of the complexity of certain parts of the language. For instance, the rules for numeric conversions. scenario is when the weak_ptr logically must be non-empty. In that case, testing for an empty shared_ptr is easy to forgetand because the shared_ptr constructor throws an exception when handed. thrown, and therefore the function leaves scope immediately; catching and handling the error will be handled where it's suitable. This is much better than explicitly testing for an empty shared_ptr

Ngày đăng: 07/07/2014, 08:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan