shared_ptr使用
1.get() 返回对象指针;use_count() 返回对象的引用计数
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr::shared_ptr;
- class Foo
- {
- public:
- void print()
- {
- cout << "foo::print" << endl;
- }
- };
- /* When sp2 is created, sp1 increments the reference counter.
- * When the two shared pointer objects get out of scope, the last
- * one that is destroyed will release the resource.
- *
- * output:
- * foo::print
- * sp1 pointer: 0x90a7008
- * foo::print
- * sp1 pointer: 0x90a7008
- * sp2 pointer: 0x90a7008
- * counter sp1: 2
- * counter sp2: 2
- */
- int main()
- {
- shared_ptr<Foo> sp1(new Foo);
- sp1->print();
- cout << "sp1 pointer: " << sp1.get() << endl;
- shared_ptr<Foo> sp2(sp1);
- sp2->print();
- cout << "sp1 pointer: " << sp1.get() << endl;
- cout << "sp2 pointer: " << sp2.get() << endl;
- cout << "counter sp1: " << sp1.use_count() << endl;
- cout << "counter sp2: " << sp2.use_count() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr::shared_ptr;
class Foo
{
public:
void print()
{
cout << "foo::print" << endl;
}
};
/* When sp2 is created, sp1 increments the reference counter.
* When the two shared pointer objects get out of scope, the last
* one that is destroyed will release the resource.
*
* output:
* foo::print
* sp1 pointer: 0x90a7008
* foo::print
* sp1 pointer: 0x90a7008
* sp2 pointer: 0x90a7008
* counter sp1: 2
* counter sp2: 2
*/
int main()
{
shared_ptr<Foo> sp1(new Foo);
sp1->print();
cout << "sp1 pointer: " << sp1.get() << endl;
shared_ptr<Foo> sp2(sp1);
sp2->print();
cout << "sp1 pointer: " << sp1.get() << endl;
cout << "sp2 pointer: " << sp2.get() << endl;
cout << "counter sp1: " << sp1.use_count() << endl;
cout << "counter sp2: " << sp2.use_count() << endl;
return 0;
}
2.相比较shared_ptr,auto_ptr在赋值与别人后,是放弃对象引用的。
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- class Foo
- {
- public:
- void print()
- {
- cout << "foo::print" << endl;
- }
- };
- /* The next sample shows a shared_ptr created from an auto_ptr object. The auto pointer gives up the ownership of the resource,
- * resetting its wrapped pointer to NULL.
- *
- * output:
- * foo::print
- * ap1 pointer: 0x99b8008
- * foo::print
- * ap1 pointer: 0
- * sp1 pointer: 0x99b8008
- */
- int main()
- {
- auto_ptr<Foo> ap1(new Foo);
- ap1->print();
- cout << "ap1 pointer: " << ap1.get() << endl;
- shared_ptr<Foo> sp1(ap1); // 注意这里是shared_ptr
- sp1->print();
- cout << "ap1 pointer: " << ap1.get() << endl;
- cout << "sp1 pointer: " << sp1.get() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
class Foo
{
public:
void print()
{
cout << "foo::print" << endl;
}
};
/* The next sample shows a shared_ptr created from an auto_ptr object. The auto pointer gives up the ownership of the resource,
* resetting its wrapped pointer to NULL.
*
* output:
* foo::print
* ap1 pointer: 0x99b8008
* foo::print
* ap1 pointer: 0
* sp1 pointer: 0x99b8008
*/
int main()
{
auto_ptr<Foo> ap1(new Foo);
ap1->print();
cout << "ap1 pointer: " << ap1.get() << endl;
shared_ptr<Foo> sp1(ap1); // 注意这里是shared_ptr
sp1->print();
cout << "ap1 pointer: " << ap1.get() << endl;
cout << "sp1 pointer: " << sp1.get() << endl;
return 0;
}
3.在shared_ptr构造函数中,行参指定构造对象和析构对象的函数
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- class Foo
- {
- public:
- void print()
- {
- cout << "foo::print" << endl;
- }
- };
- class FooHandler
- {
- public:
- static Foo* alloc()
- {
- Foo* f = new Foo;
- cout << "a new foo was created" << endl;
- return f;
- }
- static void free(Foo* f)
- {
- delete f;
- cout << "foo destroyed" << endl;
- }
- };
- /*
- * Each time a new object is created or destroyed, a message is printed in the output window (for simplicity, you will ignore the copy
- * construction or assignment). Function FooHandler::free can be provided as a delete to the shared_ptr constructor. As a result,
- * when the resource is deleted a message is printed in the output window (you have to run in debugger to see it).
- *
- * output:
- * a new foo was created
- * foo::print
- * foo destroyed
- */
- int main()
- {
- shared_ptr<Foo> ptr(FooHandler::alloc(), FooHandler::free);
- ptr->print();
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
class Foo
{
public:
void print()
{
cout << "foo::print" << endl;
}
};
class FooHandler
{
public:
static Foo* alloc()
{
Foo* f = new Foo;
cout << "a new foo was created" << endl;
return f;
}
static void free(Foo* f)
{
delete f;
cout << "foo destroyed" << endl;
}
};
/*
* Each time a new object is created or destroyed, a message is printed in the output window (for simplicity, you will ignore the copy
* construction or assignment). Function FooHandler::free can be provided as a delete to the shared_ptr constructor. As a result,
* when the resource is deleted a message is printed in the output window (you have to run in debugger to see it).
*
* output:
* a new foo was created
* foo::print
* foo destroyed
*/
int main()
{
shared_ptr<Foo> ptr(FooHandler::alloc(), FooHandler::free);
ptr->print();
return 0;
}
4.get() 返回对象指针,使用->调用成员函数
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- class Foo
- {
- public:
- void print()
- {
- cout << "foo::print" << endl;
- }
- };
- /*
- * Function get() returns the wrapped pointer to the resource (basically identical to operator-> and available for compatibility
- * with auto_ptr).
- *
- * output:
- * foo::print
- */
- int main()
- {
- shared_ptr<Foo> sp(new Foo);
- Foo* f = sp.get();
- if (f != NULL)
- f->print();
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
class Foo
{
public:
void print()
{
cout << "foo::print" << endl;
}
};
/*
* Function get() returns the wrapped pointer to the resource (basically identical to operator-> and available for compatibility
* with auto_ptr).
*
* output:
* foo::print
*/
int main()
{
shared_ptr<Foo> sp(new Foo);
Foo* f = sp.get();
if (f != NULL)
f->print();
return 0;
}
5.get() 返回对象指针,if判断是否为null
- #include <iostream>
- #include <tr1/memory>
- #include <string>
- using namespace std;
- using std::tr1::shared_ptr;
- /* Class shared_ptr defines a bool operator that allows shared pointers to be used in boolean expressions.
- * With auto_ptr, that is not possible; you have to use function get() to access the internal pointer and check it against NULL.
- */
- class PtrUtil
- {
- public:
- static void is_empty(shared_ptr<string>& ptr)
- {
- ptr != NULL ? cout << "not empty" << endl
- : cout << "is empty" << endl;
- }
- };
- /*
- * output:
- * is empty
- * not empty
- */
- int main()
- {
- shared_ptr<string> sp1;
- shared_ptr<string> sp2(new string("demo"));
- PtrUtil::is_empty(sp1);
- PtrUtil::is_empty(sp2);
- return 0;
- }
#include <iostream>
#include <tr1/memory>
#include <string>
using namespace std;
using std::tr1::shared_ptr;
/* Class shared_ptr defines a bool operator that allows shared pointers to be used in boolean expressions.
* With auto_ptr, that is not possible; you have to use function get() to access the internal pointer and check it against NULL.
*/
class PtrUtil
{
public:
static void is_empty(shared_ptr<string>& ptr)
{
ptr != NULL ? cout << "not empty" << endl
: cout << "is empty" << endl;
}
};
/*
* output:
* is empty
* not empty
*/
int main()
{
shared_ptr<string> sp1;
shared_ptr<string> sp2(new string("demo"));
PtrUtil::is_empty(sp1);
PtrUtil::is_empty(sp2);
return 0;
}
6.swap() 交换两个shared_ptr所指向的对象
- #include <iostream>
- #include <tr1/memory>
- #include <string>
- using namespace std;
- using std::tr1::shared_ptr;
- /* Class shared_ptr defines a bool operator that allows shared pointers to be used in boolean expressions.
- * With auto_ptr, that is not possible; you have to use function get() to access the internal pointer and check it against NULL.
- */
- class PtrUtil
- {
- public:
- static void is_empty(shared_ptr<string> ptr)
- {
- ptr != NULL ? cout << "not empty" << endl
- : cout << "is empty" << endl;
- }
- };
- /* Method swap() : exchange the content of the shared pointers.
- *
- * output:
- * is empty
- * not empty
- * not empty
- * is empty
- */
- int main()
- {
- shared_ptr<string> sp1;
- shared_ptr<string> sp2(new string("demo"));
- PtrUtil::is_empty(sp1);
- PtrUtil::is_empty(sp2);
- sp1.swap(sp2);
- PtrUtil::is_empty(sp1);
- PtrUtil::is_empty(sp2);
- return 0;
- }
#include <iostream>
#include <tr1/memory>
#include <string>
using namespace std;
using std::tr1::shared_ptr;
/* Class shared_ptr defines a bool operator that allows shared pointers to be used in boolean expressions.
* With auto_ptr, that is not possible; you have to use function get() to access the internal pointer and check it against NULL.
*/
class PtrUtil
{
public:
static void is_empty(shared_ptr<string> ptr)
{
ptr != NULL ? cout << "not empty" << endl
: cout << "is empty" << endl;
}
};
/* Method swap() : exchange the content of the shared pointers.
*
* output:
* is empty
* not empty
* not empty
* is empty
*/
int main()
{
shared_ptr<string> sp1;
shared_ptr<string> sp2(new string("demo"));
PtrUtil::is_empty(sp1);
PtrUtil::is_empty(sp2);
sp1.swap(sp2);
PtrUtil::is_empty(sp1);
PtrUtil::is_empty(sp2);
return 0;
}
7.使用等号赋值
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- /* operator= is overloaded so that a shared pointer can be assigned from another shared_ptr or auto_ptr.
- *
- * output:
- * sp1 = 1
- * sp2 = 2
- * sp1 = 2
- */
- int main()
- {
- shared_ptr<int> sp1(new int(1));
- cout << "sp1 = " << *sp1 << endl;
- shared_ptr<int> sp2(new int(2));
- cout << "sp2 = " << *sp2 << endl;
- sp1 = sp2;
- cout << "sp1 = " << *sp1 << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
/* operator= is overloaded so that a shared pointer can be assigned from another shared_ptr or auto_ptr.
*
* output:
* sp1 = 1
* sp2 = 2
* sp1 = 2
*/
int main()
{
shared_ptr<int> sp1(new int(1));
cout << "sp1 = " << *sp1 << endl;
shared_ptr<int> sp2(new int(2));
cout << "sp2 = " << *sp2 << endl;
sp1 = sp2;
cout << "sp1 = " << *sp1 << endl;
return 0;
}
8.unique() 判断当前对象的引用计数==1? (
比调用use_count()==1要快)
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- /* Method use_count() returns the number of references to the shared resource (pointed by the current shared pointer object).
- * Method unique() indicates whether another shared pointed shares the ownership of the same resource or not
- * (basically, it's identical to 1 == use_count()).
- *
- * output:
- * unique : true
- * counter : 1
- * unique : false
- * counter : 2
- */
- int main()
- {
- shared_ptr<std::string> sp1(new string("marius bancila"));
- cout << "unique : " << std::boolalpha << sp1.unique() << endl;
- cout << "counter : " << sp1.use_count() << endl;
- shared_ptr<std::string> sp2(sp1);
- cout << "unique : " << std::boolalpha << sp1.unique() << endl;
- cout << "counter : " << sp1.use_count() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
/* Method use_count() returns the number of references to the shared resource (pointed by the current shared pointer object).
* Method unique() indicates whether another shared pointed shares the ownership of the same resource or not
* (basically, it's identical to 1 == use_count()).
*
* output:
* unique : true
* counter : 1
* unique : false
* counter : 2
*/
int main()
{
shared_ptr<std::string> sp1(new string("marius bancila"));
cout << "unique : " << std::boolalpha << sp1.unique() << endl;
cout << "counter : " << sp1.use_count() << endl;
shared_ptr<std::string> sp2(sp1);
cout << "unique : " << std::boolalpha << sp1.unique() << endl;
cout << "counter : " << sp1.use_count() << endl;
return 0;
}
9.reset() 清空当前shared指针,并将所有基于该指针创建的shared指针的引用计数减1, 如果为0, 则删除所指对象。
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- class Foo {
- public:
- void print()
- {
- cout << " foo::print" << endl;
- }
- };
- /*Function reset() decrements the shared reference counter. It then transforms the shared pointer to an empty shared_ptr.
- *
- * output:
- * counter sp1: 1
- * counter sp1: 3
- * counter sp2: 3
- * counter sp3: 3
- * counter sp1: 0
- * counter sp2: 2
- * counter sp3: 2
- * counter sp1: 0
- * counter sp2: 0
- * counter sp3: 1
- */
- int main()
- {
- // a shared_ptr owns the resouce, counter is 1
- shared_ptr<Foo> sp1(new Foo);
- cout << "counter sp1: " << sp1.use_count() << endl;
- shared_ptr<Foo> sp2(sp1);
- shared_ptr<Foo> sp3(sp2);
- cout << "counter sp1: " << sp1.use_count() << endl;
- cout << "counter sp2: " << sp2.use_count() << endl;
- cout << "counter sp3: " << sp3.use_count() << endl;
- // first shared_ptr is reset, the counter decremented and the object becomes empty
- sp1.reset();
- cout << "counter sp1: " << sp1.use_count() << endl;
- cout << "counter sp2: " << sp2.use_count() << endl;
- cout << "counter sp3: " << sp3.use_count() << endl;
- sp2.reset();
- cout << "counter sp1: " << sp1.use_count() << endl;
- cout << "counter sp2: " << sp2.use_count() << endl;
- cout << "counter sp3: " << sp3.use_count() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
class Foo {
public:
void print()
{
cout << " foo::print" << endl;
}
};
/*Function reset() decrements the shared reference counter. It then transforms the shared pointer to an empty shared_ptr.
*
* output:
* counter sp1: 1
* counter sp1: 3
* counter sp2: 3
* counter sp3: 3
* counter sp1: 0
* counter sp2: 2
* counter sp3: 2
* counter sp1: 0
* counter sp2: 0
* counter sp3: 1
*/
int main()
{
// a shared_ptr owns the resouce, counter is 1
shared_ptr<Foo> sp1(new Foo);
cout << "counter sp1: " << sp1.use_count() << endl;
shared_ptr<Foo> sp2(sp1);
shared_ptr<Foo> sp3(sp2);
cout << "counter sp1: " << sp1.use_count() << endl;
cout << "counter sp2: " << sp2.use_count() << endl;
cout << "counter sp3: " << sp3.use_count() << endl;
// first shared_ptr is reset, the counter decremented and the object becomes empty
sp1.reset();
cout << "counter sp1: " << sp1.use_count() << endl;
cout << "counter sp2: " << sp2.use_count() << endl;
cout << "counter sp3: " << sp3.use_count() << endl;
sp2.reset();
cout << "counter sp1: " << sp1.use_count() << endl;
cout << "counter sp2: " << sp2.use_count() << endl;
cout << "counter sp3: " << sp3.use_count() << endl;
return 0;
}
10.对引用计数的理解,在容器中使用shared_ptr
- #include <iostream>
- #include <tr1/memory>
- #include <vector>
- #include <algorithm>
- using namespace std;
- using std::tr1::shared_ptr;
- /* The following sample shows a vector of shared_ptr to int; a transformation is applied on the elements of the vector,
- * doubling the value of the pointed objects.
- *
- * The program shows the reference counter to show that calling function double_it() does not affect it, even though this function
- * returns a shared_ptr by value.
- */
- shared_ptr<int> double_it(const shared_ptr<int>& sp)
- {
- *sp *= 2;
- return sp;
- }
- /*
- * output:
- * initially
- * 1 (counter = 1)
- * 2 (counter = 1)
- * 3 (counter = 1)
- * after transformation
- * 2 (counter = 1)
- * 4 (counter = 1)
- * 6 (counter = 1)
- */
- int main()
- {
- vector<shared_ptr<int> > numbers;
- numbers.push_back(shared_ptr<int>(new int(1)));
- numbers.push_back(shared_ptr<int>(new int(2)));
- numbers.push_back(shared_ptr<int>(new int(3)));
- cout << "initially" << endl;
- for (vector<shared_ptr<int> >::const_iterator it = numbers.begin(); it != numbers.end(); ++it)
- cout << **it << " (counter = " << (*it).use_count() << ")" << endl;
- std::transform(numbers.begin(), numbers.end(), numbers.begin(), double_it);
- cout << "after transformation" << endl;
- for (vector<shared_ptr<int> >::const_iterator it = numbers.begin(); it != numbers.end(); ++it)
- cout << **it << " (counter = " << (*it).use_count() << ")" << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
#include <vector>
#include <algorithm>
using namespace std;
using std::tr1::shared_ptr;
/* The following sample shows a vector of shared_ptr to int; a transformation is applied on the elements of the vector,
* doubling the value of the pointed objects.
*
* The program shows the reference counter to show that calling function double_it() does not affect it, even though this function
* returns a shared_ptr by value.
*/
shared_ptr<int> double_it(const shared_ptr<int>& sp)
{
*sp *= 2;
return sp;
}
/*
* output:
* initially
* 1 (counter = 1)
* 2 (counter = 1)
* 3 (counter = 1)
* after transformation
* 2 (counter = 1)
* 4 (counter = 1)
* 6 (counter = 1)
*/
int main()
{
vector<shared_ptr<int> > numbers;
numbers.push_back(shared_ptr<int>(new int(1)));
numbers.push_back(shared_ptr<int>(new int(2)));
numbers.push_back(shared_ptr<int>(new int(3)));
cout << "initially" << endl;
for (vector<shared_ptr<int> >::const_iterator it = numbers.begin(); it != numbers.end(); ++it)
cout << **it << " (counter = " << (*it).use_count() << ")" << endl;
std::transform(numbers.begin(), numbers.end(), numbers.begin(), double_it);
cout << "after transformation" << endl;
for (vector<shared_ptr<int> >::const_iterator it = numbers.begin(); it != numbers.end(); ++it)
cout << **it << " (counter = " << (*it).use_count() << ")" << endl;
return 0;
}
11.多态情况下的shared指针使用(声明基类句柄,创建子类对象)
- #include <iostream>
- #include <tr1/memory>
- #include <vector>
- #include <string>
- using namespace std;
- using std::tr1::shared_ptr;
- /*shared_ptr can work with class hierarchies, so that shared<D> is convertible to shared<B>, where D is a class (or struct) derived
- * from B. The following class hierarchy is used to demonstrate the concept.
- */
- class Item
- {
- string title_;
- public:
- Item(const string& title) : title_(title){}
- virtual ~Item(){}
- virtual string Description() const = 0;
- string Title() const
- {
- return title_;
- }
- };
- class Book: public Item
- {
- int pages_;
- public:
- Book(const string& title, int pages):Item(title), pages_(pages){}
- virtual string Description() const
- {
- return "Book: " + Title();
- }
- int Pages() const
- {
- return pages_;
- }
- };
- class DVD: public Item
- {
- int tracks_;
- public:
- DVD(const string& title, int tracks):Item(title), tracks_(tracks){}
- virtual string Description() const
- {
- return "DVD: " + Title();
- }
- int Tracks() const
- {
- return tracks_;
- }
- };
- /*
- * output:
- * Book: Effective STL
- * DVD: Left of the Middle
- */
- int main()
- {
- vector<shared_ptr<Item> > items;
- items.push_back(shared_ptr<Book>(new Book("Effective STL", 400)));
- items.push_back(shared_ptr<DVD>(new DVD("Left of the Middle", 14)));
- for (vector<shared_ptr<Item> >::const_iterator it = items.begin(); it != items.end(); ++it)
- cout << (*it)->Description() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
#include <vector>
#include <string>
using namespace std;
using std::tr1::shared_ptr;
/*shared_ptr can work with class hierarchies, so that shared<D> is convertible to shared<B>, where D is a class (or struct) derived
* from B. The following class hierarchy is used to demonstrate the concept.
*/
class Item
{
string title_;
public:
Item(const string& title) : title_(title){}
virtual ~Item(){}
virtual string Description() const = 0;
string Title() const
{
return title_;
}
};
class Book: public Item
{
int pages_;
public:
Book(const string& title, int pages):Item(title), pages_(pages){}
virtual string Description() const
{
return "Book: " + Title();
}
int Pages() const
{
return pages_;
}
};
class DVD: public Item
{
int tracks_;
public:
DVD(const string& title, int tracks):Item(title), tracks_(tracks){}
virtual string Description() const
{
return "DVD: " + Title();
}
int Tracks() const
{
return tracks_;
}
};
/*
* output:
* Book: Effective STL
* DVD: Left of the Middle
*/
int main()
{
vector<shared_ptr<Item> > items;
items.push_back(shared_ptr<Book>(new Book("Effective STL", 400)));
items.push_back(shared_ptr<DVD>(new DVD("Left of the Middle", 14)));
for (vector<shared_ptr<Item> >::const_iterator it = items.begin(); it != items.end(); ++it)
cout << (*it)->Description() << endl;
return 0;
}
12.dynamic_cast,使用dynamic_pointer_cast将基类向下转型为子类
- #include <iostream>
- #include <tr1/memory>
- #include <string>
- using namespace std;
- using std::tr1::shared_ptr;
- /*shared_ptr can work with class hierarchies, so that shared<D> is convertible to shared<B>, where D is a class (or struct) derived
- * from B. The following class hierarchy is used to demonstrate the concept.
- */
- class Item
- {
- string title_;
- public:
- Item(const string& title) : title_(title){}
- virtual ~Item(){}
- virtual string Description() const = 0;
- string Title() const
- {
- returntitle_;
- }
- };
- class Book: public Item
- {
- int pages_;
- public:
- Book(const string& title, int pages):Item(title), pages_(pages){}
- virtual string Description() const
- {
- return "Book: " + Title();
- }
- int Pages() const
- {
- return pages_;
- }
- };
- class DVD: public Item
- {
- int tracks_;
- public:
- DVD(const string& title, int tracks):Item(title), tracks_(tracks){}
- virtual string Description() const
- {
- return "DVD: " + Title();
- }
- int Tracks() const
- {
- return tracks_;
- }
- };
- /* To convert back, from shared_ptr<B> to shared_ptr<D>, where D is a class (or structure) derived from B,
- * you can use the cast function std::tr1::dynamic_pointer_cast.
- *
- * output:
- * spi counter: 1
- * Left of the Middle, 14 tracks
- * spi counter: 2
- * spb counter: 0
- * spd counter: 2
- */
- int main()
- {
- shared_ptr<Item> spi(new DVD("Left of the Middle", 14));
- cout << "spi counter: " << spi.use_count() << endl;
- shared_ptr<Book> spb = std::tr1::dynamic_pointer_cast<Book>(spi);
- if (spb != NULL)
- cout << spb->Title() << ", " << spb->Pages() << " pages" << endl;
- shared_ptr<DVD> spd = std::tr1::dynamic_pointer_cast<DVD>(spi);
- if (spd != NULL)
- cout << spd->Title() << ", " << spd->Tracks() << " tracks" << endl;
- cout << "spi counter: " << spi.use_count() << endl;
- cout << "spb counter: " << spb.use_count() << endl;
- cout << "spd counter: " << spd.use_count() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
#include <string>
using namespace std;
using std::tr1::shared_ptr;
/*shared_ptr can work with class hierarchies, so that shared<D> is convertible to shared<B>, where D is a class (or struct) derived
* from B. The following class hierarchy is used to demonstrate the concept.
*/
class Item
{
string title_;
public:
Item(const string& title) : title_(title){}
virtual ~Item(){}
virtual string Description() const = 0;
string Title() const
{
returntitle_;
}
};
class Book: public Item
{
int pages_;
public:
Book(const string& title, int pages):Item(title), pages_(pages){}
virtual string Description() const
{
return "Book: " + Title();
}
int Pages() const
{
return pages_;
}
};
class DVD: public Item
{
int tracks_;
public:
DVD(const string& title, int tracks):Item(title), tracks_(tracks){}
virtual string Description() const
{
return "DVD: " + Title();
}
int Tracks() const
{
return tracks_;
}
};
/* To convert back, from shared_ptr<B> to shared_ptr<D>, where D is a class (or structure) derived from B,
* you can use the cast function std::tr1::dynamic_pointer_cast.
*
* output:
* spi counter: 1
* Left of the Middle, 14 tracks
* spi counter: 2
* spb counter: 0
* spd counter: 2
*/
int main()
{
shared_ptr<Item> spi(new DVD("Left of the Middle", 14));
cout << "spi counter: " << spi.use_count() << endl;
shared_ptr<Book> spb = std::tr1::dynamic_pointer_cast<Book>(spi);
if (spb != NULL)
cout << spb->Title() << ", " << spb->Pages() << " pages" << endl;
shared_ptr<DVD> spd = std::tr1::dynamic_pointer_cast<DVD>(spi);
if (spd != NULL)
cout << spd->Title() << ", " << spd->Tracks() << " tracks" << endl;
cout << "spi counter: " << spi.use_count() << endl;
cout << "spb counter: " << spb.use_count() << endl;
cout << "spd counter: " << spd.use_count() << endl;
return 0;
}
13.static cast,使用static_pointer_cast将void转型为char,观察引用计数的变化
- #include <iostream>
- #include <tr1/memory>
- #include <vector>
- using namespace std;
- using std::tr1::shared_ptr;
- /* A second cast function is std::tr1::static_pointer_cast. It returns an empty shared_ptr if the original object is empty,
- * or a shared_ptr<T> object that owns the resource that is owned by the original object. The expression static_cast<T*>(r.get())
- * must be valid.
- *
- * In the next sample, a vector holds shared_ptr to void. The first element is statically cast to shared_ptr<char>.
- * The cast is valid as long as the source is not empty, regardless of whether the types are compatible or not.
- *
- * output:
- * after creating the shared pointer
- * -1 sp1 counter: 1
- * after adding to the vector
- * -2 sp1 counter: 2
- * A
- * after casting
- * -3 sp1 counter: 3
- * -4 spc counter: 3
- */
- int main()
- {
- vector<shared_ptr<void> > items;
- shared_ptr<char> sp1(new char('A'));
- shared_ptr<short> sp2(new short(66));
- cout << "after creating the shared pointer" << endl;
- cout << "-1 sp1 counter: " << sp1.use_count() << endl;
- items.push_back(sp1);
- items.push_back(sp2);
- cout << "after adding to the vector" << endl;
- cout << "-2 sp1 counter: " << sp1.use_count() << endl;
- shared_ptr<char> spc = tr1::static_pointer_cast<char>(*(items.begin()));
- if (spc != NULL)
- cout << *spc << endl;
- cout << "after casting" << endl;
- cout << "-3 sp1 counter: " << sp1.use_count() << endl;
- cout << "-4 spc counter: " << spc.use_count() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
#include <vector>
using namespace std;
using std::tr1::shared_ptr;
/* A second cast function is std::tr1::static_pointer_cast. It returns an empty shared_ptr if the original object is empty,
* or a shared_ptr<T> object that owns the resource that is owned by the original object. The expression static_cast<T*>(r.get())
* must be valid.
*
* In the next sample, a vector holds shared_ptr to void. The first element is statically cast to shared_ptr<char>.
* The cast is valid as long as the source is not empty, regardless of whether the types are compatible or not.
*
* output:
* after creating the shared pointer
* -1 sp1 counter: 1
* after adding to the vector
* -2 sp1 counter: 2
* A
* after casting
* -3 sp1 counter: 3
* -4 spc counter: 3
*/
int main()
{
vector<shared_ptr<void> > items;
shared_ptr<char> sp1(new char('A'));
shared_ptr<short> sp2(new short(66));
cout << "after creating the shared pointer" << endl;
cout << "-1 sp1 counter: " << sp1.use_count() << endl;
items.push_back(sp1);
items.push_back(sp2);
cout << "after adding to the vector" << endl;
cout << "-2 sp1 counter: " << sp1.use_count() << endl;
shared_ptr<char> spc = tr1::static_pointer_cast<char>(*(items.begin()));
if (spc != NULL)
cout << *spc << endl;
cout << "after casting" << endl;
cout << "-3 sp1 counter: " << sp1.use_count() << endl;
cout << "-4 spc counter: " << spc.use_count() << endl;
return 0;
}
14.const cast,如果声明std::tr1::shared_ptr<const int> csp,可以声明
std::tr1::shared_ptr<int> sp = std::tr1::const_pointer_cast<int>(csp);
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- /* To modify the value of the pointer object the const specifier must be removed. This is shown below.
- *
- * output:
- * csp counter: 1
- * 15
- * 15
- * csp counter: 2
- * sp counter: 2
- */
- int main()
- {
- shared_ptr<const int> csp(new int(5));
- cout << "csp counter: " << csp.use_count() << endl;
- shared_ptr<int> sp = std::tr1::const_pointer_cast<int>(csp);
- *sp += 10;
- cout << *csp << endl;
- cout << *sp << endl;
- cout << "csp counter: " << csp.use_count() << endl;
- cout << "sp counter: " << sp.use_count() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
/* To modify the value of the pointer object the const specifier must be removed. This is shown below.
*
* output:
* csp counter: 1
* 15
* 15
* csp counter: 2
* sp counter: 2
*/
int main()
{
shared_ptr<const int> csp(new int(5));
cout << "csp counter: " << csp.use_count() << endl;
shared_ptr<int> sp = std::tr1::const_pointer_cast<int>(csp);
*sp += 10;
cout << *csp << endl;
cout << *sp << endl;
cout << "csp counter: " << csp.use_count() << endl;
cout << "sp counter: " << sp.use_count() << endl;
return 0;
}
15.weak_ptr的lock() 类似于shared_ptr的get()
- #include <iostream>
- #include <tr1/memory>
- using namespace std;
- using std::tr1::shared_ptr;
- using std::tr1::weak_ptr;
- /* The major weakness of shared_ptr is that it cannot detect cyclic dependencies. In this case, the reference counter is incremented
- * more than it should actually be, so that the resources are no longer released when the shared pointer objects go out of scope.
- * To fix this problem, a second smart pointer was created, weak_ptr, that points to a resource owned by a shared_ptr but does not
- * affect the reference counter; it is a "weak reference." When the last shared_ptr that owns the resource referred by a weak_ptr,
- * the resource is released and the weak pointer is marked as invalid. To check whether a weak_ptr is valid or not, you can use
- * function expired() that returns true if the pointer was marked as invalid.
- */
- /* Even though function get() (that provides direct access to the wrapped pointer) is available, it's not recommended to use it even
- * in single-threaded applications. The safe alternative is function lock() that returns a shread_ptr sharing the resource pointed by
- * the weak pointer.
- */
- void show(const weak_ptr<int>& wp)
- {
- shared_ptr<int> sp = wp.lock();
- cout << *sp << endl;
- }
- /*
- * output:
- * 44
- * expired : true
- */
- int main()
- {
- weak_ptr<int> wp;
- {
- shared_ptr<int> sp(new int(44));
- wp = sp;
- show(wp);
- }
- cout << "expired : " << boolalpha << wp.expired() << endl;
- return 0;
- }
#include <iostream>
#include <tr1/memory>
using namespace std;
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
/* The major weakness of shared_ptr is that it cannot detect cyclic dependencies. In this case, the reference counter is incremented
* more than it should actually be, so that the resources are no longer released when the shared pointer objects go out of scope.
* To fix this problem, a second smart pointer was created, weak_ptr, that points to a resource owned by a shared_ptr but does not
* affect the reference counter; it is a "weak reference." When the last shared_ptr that owns the resource referred by a weak_ptr,
* the resource is released and the weak pointer is marked as invalid. To check whether a weak_ptr is valid or not, you can use
* function expired() that returns true if the pointer was marked as invalid.
*/
/* Even though function get() (that provides direct access to the wrapped pointer) is available, it's not recommended to use it even
* in single-threaded applications. The safe alternative is function lock() that returns a shread_ptr sharing the resource pointed by
* the weak pointer.
*/
void show(const weak_ptr<int>& wp)
{
shared_ptr<int> sp = wp.lock();
cout << *sp << endl;
}
/*
* output:
* 44
* expired : true
*/
int main()
{
weak_ptr<int> wp;
{
shared_ptr<int> sp(new int(44));
wp = sp;
show(wp);
}
cout << "expired : " << boolalpha << wp.expired() << endl;
return 0;
}
16.一个使用shared_ptr和weak_ptr的二叉树数据结构示例
- #include <iostream>
- #include <tr1/memory>
- #include <vector>
- #include <string>
- using namespace std;
- using std::tr1::shared_ptr;
- using std::tr1::weak_ptr;
- /* The following sample shows such a tree, but uses a weak_ptr to solve the cyclic dependency.*/
- class Node
- {
- string value_;
- shared_ptr<Node> left_;
- shared_ptr<Node> right_;
- weak_ptr<Node> parent_;
- public:
- Node(const string value):value_(value){}
- string Value() const { return value_; }
- shared_ptr<Node> Left() const { return left_; }
- shared_ptr<Node> Right() const { return right_; }
- weak_ptr<Node> Parent() const { return parent_; }
- void SetParent(shared_ptr<Node> node)
- {
- parent_.reset();
- parent_ = node;
- }
- void SetLeft(shared_ptr<Node> node)
- {
- left_.reset();
- left_ = node;
- }
- void SetRight(shared_ptr<Node> node)
- {
- right_.reset();
- right_ = node;
- }
- };
- string path(const shared_ptr<Node>& item)
- {
- weak_ptr<Node> wparent = item->Parent();
- shared_ptr<Node> sparent = wparent.lock();
- if (sparent)
- {
- return path(sparent) + "\\" + item->Value();
- }
- return item->Value();
- }
- /*
- * output:
- * C:\dir1\dir11
- */
- int main()
- {
- shared_ptr<Node> root(new Node("C:"));
- shared_ptr<Node> child1(new Node("dir1"));
- shared_ptr<Node> child2(new Node("dir2"));
- root->SetLeft(child1);
- child1->SetParent(root);
- root->SetRight(child2);
- child2->SetParent(root);
- shared_ptr<Node> child11(new Node("dir11"));
- child1->SetLeft(child11);
- child11->SetParent(child1);
- cout << "path: " << path(child11) << endl;
- return 0;
- }