1.智能指针
std::unique_ptr(single ownership)
std::shared_ptr(shared ownership)
std::weak_ptr(temp/no ownership)
C++11
以后出现- 定义在头文件
<memory>
中
1.0 为啥要有智能指针?
普通指针
void bar(Entity* e)
{
// who owns e
// How long is e's life cycle?
// Should I delete e?
}
void foo()
{
Entity *e = new Entity();
e->DoSomething();
bar(e);
}
foo();
// out of scope, memory leak
智能指针
void bar(Entity* e)
{
// bar owns e
// e will be automatically destroyed
}
void foo()
{
std::unique_ptr<Entity> e = std::make_unique<Entity>();
e->DoSomething();
bar(std::move(e));
}
foo();
// No memory leak
1.1 std::unique_ptr
std::unique_ptr<Entity> e1 = new Entity(); // non-assignable
std::unique_ptr<Entity> e1(new Entity()); // ok
std::unique_ptr<Entity> e1 = std::make_unique<Entity>(); // preferred
auto e2 = std::make_unique<Entity>(); // preferred
std::unique_ptr<Entity> e2 = e1; // non-copyable
std::unique_ptr<Entity> e2 = std::move(e1); // movable, transfer ownership
foo(std::move(e1)); // transfer ownership
#include <iostream>
#include <memory>
class Entity {
public:
Entity() {
puts("Entity created!"); }
~Entity() {
puts("Entity destroyed!"); }
};
void ex1() {
puts("--------");
puts("Entering ex1");
{
puts("Entering ex1::scope1");
auto e1 = std::make_unique<Entity>();
puts("Leaving ex1::scope1");
}
puts("Leaving ex1");
}
void foo(std::unique_ptr<Entity>) {
puts("Entering foo");
puts("Leaving foo");
}
void ex2() {
puts("--------");
puts("Entering ex2");
auto e1 = std::make_unique<Entity>();
foo(std::move(e1));
// e1 was destoried.
puts("Leaving ex2");
}
int main(int argc, char** argv) {
ex1();
ex2();
return 0;
}
输出
--------
Entering ex1
Entering ex1::scope1
Entity created!
Leaving ex1::scope1
Entity destroyed!
Leaving ex1
--------
Entering ex2
Entity created!
Entering foo
Leaving foo
Entity destroyed!
Leaving ex2
1.2 std::shared_ptr
std::shared_ptr<Entity> e1(new Entity()); // ok
std::shared_ptr<Entity> e1 = std::make_shared<Entity>(); // preferred
auto e2 = std::make_shared<Entity>(); // preferred
std::shared_ptr<Entity> e2 = e1; // copyable, use_count + 1
std::shared_ptr<Entity> e2 = std::move(e1); // movable, use_count remains
foo(e1); // use_count + 1
foo(std::move(e1)); // use_count remains
#include <iostream>
#include <memory>
class Entity {
public:
Entity() {
puts("Entity created!"); }
~Entity() {
puts("Entity destroyed!"); }
};
void ex3() {
puts("--------");
puts("Entering ex3");
auto e1 = std::make_shared<Entity>();
std::cout << e1.use_count() << std::endl;
{
puts("Entering ex3::scope1");
auto e2 = e1; // use_count ++
std::cout << e1.use_count() << std::endl;
auto e3 = std::move(e2); // use_count remains
std::cout << e1.use_count() << std::endl;
puts("Leaving ex3::scope1");
}
std::cout << e1.use_count() << std::endl;
puts("Leaving ex3");
}
int main(int argc, char** argv) {
ex3();
return 0;
}
输出
--------
Entering ex3
Entity created!
1
Entering ex3::scope1
2
2
Leaving ex3::scope1
1
Leaving ex3
Entity destroyed!
1.3 std::weak_ptr
Must be converted to a std::shared_ptr before accessing
Models a temporary ownership
Access if the object still exist
Ok if the object was already destroyed
auto e1 = std::make_shared<Entity>();
std::weak_ptr<Entity> ew = e1; // construct from a shared_ptr`
if (std::shared_ptr<Entity> e2 = ew.lock()) // convert to a shared_ptr
e2->DoSomething();
#include <iostream>
#include <memory>
class Entity {
public:
Entity() {
puts("Entity created!"); }
~Entity() {
puts("Entity destroyed!"); }
};
void observe(std::weak_ptr<Entity> ew) {
if (std::shared_ptr<Entity> spt = ew.lock()) {
std::cout << spt.use_count() << std::endl;
std::cout << "entity still alive!" << std::endl;
} else {
std::cout << "entity was expired !" << std::endl;
}
}
void ex4() {
puts("--------");
puts("Entering ex4");
std::weak_ptr<Entity> ew;
{
puts("Entering ex4::scope1");
auto e1 = std::make_shared<Entity>();
std::cout << e1.use_count() << std::endl;
ew = e1; // use_count remains
std::cout << e1.use_count() << std::endl;
observe(ew);
puts("Leaving ex4::scope1");
}
observe(ew);
puts("Leaving ex4");
}
int main(int argc, char** argv) {
ex4();
return 0;
}
输出
--------
Entering ex4
Entering ex4::scope1
Entity created!
1
1
2
entity still alive!
Leaving ex4::scope1
Entity destroyed!
entity was expired !
Leaving ex4
总结
- 能用智能指针就用智能指针,不再使用
new/delete
- 能用
std::unique_ptr
就不用std::shared_ptr
- 尽量使用
move std::shared_ptr