1. Trang chủ
  2. » Công Nghệ Thông Tin

HandBooks Professional Java-C-Scrip-SQL part 44 pps

6 134 0
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 32,33 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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 wea

Trang 1

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

Trang 2

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>

Trang 3

#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

Trang 4

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

Trang 5

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

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