福州晋安区建设局网站,淘宝网站建设可行性分析,宜兴网站策划,广告设计介绍内存管理-unique_ptr 一、概述二、成员函数1. 构造、析构函数函数1. 构造函数2. 析构函数3. 赋值号 2. 修改器1. release#xff08;#xff09;2. reset()3. swap() 3. 观察器1. get()2. get_deleter3. bool 运算 一、概述
std::unique_ptr 是通过指针占有并管理另一对象2. reset()3. swap() 3. 观察器1. get()2. get_deleter3. bool 运算 一、概述
std::unique_ptr 是通过指针占有并管理另一对象并在 unique_ptr 离开作用域时释放该对象的智能指针。相当于一个对象的指针只会被一堆 unique_ptr 中某一个被占用而且这个对象的指针不能被其他unique_ptr 占用。这个同时还有作用域的限制。
在下列的两个情况下会用调用 unique_ptr 关联的 Deleter 删除器释放对象
销毁了用于管理的 unique_ptr 对象通过 operator 或 reset() 赋值另一指针给管理的 unique_ptr 对象
通过调用 get_deleter()(ptr) 用潜在为用户提供的删除器释放对象。默认删除器用 delete 运算符它销毁定义的unique_ptr 对象并是否这个指针对象的分配内存。
这个的类的定义如下可以看到参数有两个一个是待分配的类型一个是删除器
template class T,class Deleter std::default_deleteTclass unique_ptr; template class T,class Deleterclass unique_ptrT[], Deleter; unique_ptr 亦可以不占有对象该情况下称它为空 (empty)。
std::unique_ptr 有两个版本 管理单个对象例如以 new 分配 管理动态分配的对象数组例如以 new[] 分配
注解
只有非 const 的 unique_ptr 能转移被管理对象的所有权给另一 unique_ptr 。若对象的生存期为 const std::unique_ptr 所管理则它被限定在创建指针的作用域中。
std::unique_ptr 常用于管理对象的生存期包含
通过正常退出和经由异常退出两者上的受保证删除提供异常安全给处理拥有动态生存期的对象的类和函数传递独占的拥有动态生存期的对象的所有权到函数从函数获得独占的拥有动态生存期对象的所有权作为具移动容器的元素类型例如保有指向动态分配对象的指针的 std::vector 例如若想要多态行为
std::unique_ptr 可为不完整类型 T 构造例如用于改善用作 pImpl 手法中柄的用途。若使用默认删除器则 T 必须在代码中调用删除器点处完整这发生于析构函数、移动赋值运算符和 std::unique_ptr 的 reset 成员函数中。相反地 std::shared_ptr 不能从指向不完整类型的裸指针构造但可于 T 不完整处销毁。注意若 T 是类模板特化则以 unique_ptr 为运算数的使用如 !p 因 ADL 而要求 T 的形参完整。
若 T 是某基类 B 的派生类则 std::unique_ptr 可隐式转换为 std::unique_ptr。产生的 std::unique_ptr 的默认删除器将使用 B 的 operator delete 这导致未定义行为除非 B 的析构函数为虚。注意 std::shared_ptr 表现有别 std::shared_ptr 将使用类型 T 的 operator delete 而且即使 B 的析构函数非虚也会正确删除被占有对象。
不同于 std::shared_ptr std::unique_ptr 可通过任何满足可空指针 (NullablePointer) 的定制柄类型管理对象。例如这允许管理位于共享内存但提供定义 typedef boost::offset_ptr pointer; 或其他缀饰指针的 Deleter 的对象。
例子
#include iostream
#include vector
#include memory
#include cstdio
#include fstream
#include cassert
#include functionalstruct B {virtual void bar() { std::cout B::bar\n; }virtual ~B() default;
};
struct D : B
{D() { std::cout D::D\n; }~D() { std::cout D::~D\n; }void bar() override { std::cout D::bar\n; }
};// 消费 unique_ptr 的函数能以值或以右值引用接收它
std::unique_ptrD pass_through(std::unique_ptrD p)
{p-bar();return p;
}void close_file(std::FILE* fp) { std::fclose(fp); }int main()
{std::cout unique ownership semantics demo\n;{auto p std::make_uniqueD(); // p 是占有 D 的 unique_ptrauto q pass_through(std::move(p)); assert(!p); // 现在 p 不占有任何内容并保有空指针q-bar(); // 而 q 占有 D 对象} // ~D 调用于此std::cout Runtime polymorphism demo\n;{std::unique_ptrB p std::make_uniqueD(); // p 是占有 D 的 unique_ptr// 作为指向基类的指针p-bar(); // 虚派发std::vectorstd::unique_ptrB v; // unique_ptr 能存储于容器v.push_back(std::make_uniqueD());v.push_back(std::move(p));v.emplace_back(new D);for(auto p: v) p-bar(); // 虚派发} // ~D called 3 timesstd::cout Custom deleter demo\n;std::ofstream(demo.txt) x; // 准备要读的文件{std::unique_ptrstd::FILE, void (*)(std::FILE*) fp(std::fopen(demo.txt, r),close_file);if(fp) // fopen 可以打开失败该情况下 fp 保有空指针std::cout (char)std::fgetc(fp.get()) \n;} // fclose() 调用于此但仅若 FILE* 不是空指针// 即 fopen 成功std::cout Custom lambda-expression deleter demo\n;{std::unique_ptrD, std::functionvoid(D*) p(new D, [](D* ptr){std::cout destroying from a custom deleter...\n;delete ptr;}); // p 占有 Dp-bar();} // 调用上述 lambda 并销毁 Dstd::cout Array form of unique_ptr demo\n;{std::unique_ptrD[] p{new D[3]};} // 调用 ~D 3 次
}
//输出unique ownership semantics demo
D::D
D::bar
D::bar
D::~D
Runtime polymorphism demo
D::D
D::bar
D::D
D::D
D::bar
D::bar
D::bar
D::~D
D::~D
D::~D
Custom deleter demo
x
Custom lambda-expression deleter demo
D::D
D::bar
destroying from a custom deleter...
D::~D
Array form of unique_ptr demo
D::D
D::D
D::D
D::~D
D::~D
D::~D二、成员函数
1. 构造、析构函数函数
1. 构造函数
#include iostream
#include memorystruct Foo { // 要管理的对象Foo() { std::cout Foo ctor\n; }Foo(const Foo) { std::cout Foo copy ctor\n; }Foo(Foo) { std::cout Foo move ctor\n; }~Foo() { std::cout ~Foo dtor\n; }
};struct D { // 删除器D() {};D(const D) { std::cout D copy ctor\n; }D(D) { std::cout D non-const copy ctor\n;}D(D) { std::cout D move ctor \n; }void operator()(Foo* p) const {std::cout D is deleting a Foo\n;delete p;};
};int main()
{std::cout Example constructor(1)...\n;std::unique_ptrFoo up1; // up1 为空std::unique_ptrFoo up1b(nullptr); // up1b 为空std::cout Example constructor(2)...\n;{std::unique_ptrFoo up2(new Foo); // up2 现在占有 Foo} // Foo 被删除std::cout Example constructor(3)...\n;D d;{ // 删除器类型不是引用std::unique_ptrFoo, D up3(new Foo, d); // 复制删除器}{ // 删除器类型是引用 std::unique_ptrFoo, D up3b(new Foo, d); // up3b 保有到 d 的引用}std::cout Example constructor(4)...\n;{ // 删除器不是引用std::unique_ptrFoo, D up4(new Foo, D()); // 移动删除器}std::cout Example constructor(5)...\n;{std::unique_ptrFoo up5a(new Foo);std::unique_ptrFoo up5b(std::move(up5a)); // 所有权转移}std::cout Example constructor(6)...\n;{std::unique_ptrFoo, D up6a(new Foo, d); // 复制 Dstd::unique_ptrFoo, D up6b(std::move(up6a)); // 移动 Dstd::unique_ptrFoo, D up6c(new Foo, d); // D 是引用std::unique_ptrFoo, D up6d(std::move(up6c)); // 复制 D}#if (__cplusplus 201703L)std::cout Example constructor(7)...\n;{std::auto_ptrFoo up7a(new Foo);std::unique_ptrFoo up7b(std::move(up7a)); // 所有权转移}
#endifstd::cout Example array constructor...\n;{std::unique_ptrFoo[] up(new Foo[3]);} // 删除三个 Foo 对象
}
// 输出Example constructor(1)...
Example constructor(2)...
Foo ctor
~Foo dtor
Example constructor(3)...
Foo ctor
D copy ctor
D is deleting a Foo
~Foo dtor
Foo ctor
D is deleting a Foo
~Foo dtor
Example constructor(4)...
Foo ctor
D move ctor
D is deleting a Foo
~Foo dtor
Example constructor(5)...
Foo ctor
~Foo dtor
Example constructor(6)...
Foo ctor
D copy ctor
D move ctor
Foo ctor
D non-const copy ctor
D is deleting a Foo
~Foo dtor
D is deleting a Foo
~Foo dtor
Example constructor(7)...
Foo ctor
~Foo dtor
Example array constructor...
Foo ctor
Foo ctor
Foo ctor
~Foo dtor
~Foo dtor
~Foo dtor2. 析构函数
// 下列程序演示定制删除器的用法。#include iostream
#include memoryint main ()
{auto deleter [](int* ptr){std::cout [deleter called]\n;delete ptr;};std::unique_ptrint,decltype(deleter) uniq(new int, deleter);std::cout (uniq ? not empty\n : empty\n);uniq.reset();std::cout (uniq ? not empty\n : empty\n);
}
//输出not empty
[deleter called]
empty3. 赋值号
作为只能被移动的类型unique_ptr 的赋值运算符只接受右值实参例如 std::make_unique 的结果或已被 std::move 的 unique_ptr 变量。
#include iostream
#include memorystruct Foo
{int id;Foo(int id) : id(id) { std::cout Foo id \n; }~Foo() { std::cout ~Foo id \n; }
};int main()
{std::unique_ptrFoo p1(std::make_uniqueFoo(1));{std::cout 创建新的 Foo...\n;std::unique_ptrFoo p2(std::make_uniqueFoo(2));// p1 p2; // 错误不能复制 unique_ptrp1 std::move(p2);std::cout 准备离开内层块...\n;// 即使 p2 将要离开作用域但是 Foo 示例会继续生存}std::cout 准备离开程序...\n;
}
//输出Foo 1
创建新的 Foo...
Foo 2
~Foo 1
准备离开内层块...
准备离开程序...
~Foo 22. 修改器
1. release
若存在则释放被管理对象的所有权。调用这个函数后再去 get() 就返回 nullptr 。这个本身也返回的是 nullptr值。
调用方负责删除该对象。
指向被管理对象的指针或若无被管理对象则为 nullptr 即调用前 get() 会返回的值。
#include cassert
#include iostream
#include memorystruct Foo
{Foo() { std::cout Foo\n; }~Foo() { std::cout ~Foo\n; }
};// Foo资源的所有权在调用该函数时被转移
void legacy_api(Foo* owning_foo)
{std::cout __func__ \n;// 没有人能理解或再敢碰的遗留代码// ...delete owning_foo;
}int main()
{std::unique_ptrFoo managed_foo(new Foo);legacy_api(managed_foo.release());assert(managed_foo nullptr);
}
//输出Foo
legacy_api
~Foo2. reset()
定义void reset( pointer ptr pointer() ) noexcept;
为在提供新删除器时替换被管理对象可用移动赋值运算符。
不进行自 reset 测试即 ptr 是否指向已为 *this 管理的对象除非作为编译器扩展或调试断言提供。注意如 p.reset(p.release()) 的代码不涉及自重置只有类似 p.reset(p.get()) 的代码会。
示例
#include iostream
#include memorystruct Foo {Foo() { std::cout Foo...\n; }~Foo() { std::cout ~Foo...\n; }
};struct D {void operator() (Foo* p) {std::cout Calling delete for Foo object... \n;delete p;}
};int main()
{std::cout Creating new Foo...\n;std::unique_ptrFoo, D up(new Foo(), D()); // up 占有 Foo 指针删除器 D std::cout Replace owned Foo with a new Foo...\n;up.reset(new Foo()); // 调用旧者的删除器std::cout Release and delete the owned Foo...\n;up.reset(nullptr);
}
//输出Creating new Foo...
Foo...
Replace owned Foo with a new Foo...
Foo...
Calling delete for Foo object...
~Foo...
Release and delete the owned Foo...
Calling delete for Foo object...
~Foo...3. swap()
void swap(unique_ptr other) noexcept;
交换 *this 和另一 unique_ptr 对象 other 的被管理对象和关联的删除器。
#include iostream
#include memorystruct Foo {Foo(int _val) : val(_val) { std::cout Foo...\n; }~Foo() { std::cout ~Foo...\n; }int val;
};int main()
{std::unique_ptrFoo up1(new Foo(1));std::unique_ptrFoo up2(new Foo(2));up1.swap(up2);std::cout up1-val: up1-val std::endl;std::cout up2-val: up2-val std::endl;
}
//输出Foo...
Foo...
up1-val:2
up2-val:1
~Foo...
~Foo...3. 观察器
1. get()
返回指向被管理对象的指针如果无被管理对象则为 nullptr 。
#include iomanip
#include iostream
#include memory
#include string
#include utilityclass Res {std::string s;public:Res(std::string arg) : s{ std::move(arg) } {std::cout Res::Res( std::quoted(s) );\n;}~Res() {std::cout Res::~Res();\n;}private:friend std::ostream operator (std::ostream os, Res const r) {return os Res { s std::quoted(r.s) ; };}
};int main()
{std::unique_ptrRes up(new Res{Hello, world!});Res *res up.get();std::cout *res \n;
}
//输出Res::Res(Hello, world!);
Res { s Hello, world!; }
Res::~Res();2. get_deleter
返回会用于析构被管理对象的删除器对象。
#include iostream
#include memorystruct Foo
{Foo() { std::cout Foo...\n; }~Foo() { std::cout ~Foo...\n; }
};struct D
{void bar() { std::cout Call deleter D::bar()...\n; }void operator()(Foo* p) const{std::cout Call delete for Foo object...\n;delete p;}
};int main()
{std::unique_ptrFoo, D up(new Foo(), D());D del up.get_deleter();del.bar();
}
//输出Foo...
Call deleter D::bar()...
Call delete for Foo object...
~Foo...3. bool 运算
explicit operator bool() const noexcept;检查 *this 是否占有对象即是否有 get() ! nullptr。若 *this 占有对象则为 true 否则为 false 。
#include iostream
#include memoryint main()
{std::unique_ptrint ptr(new int(42));if (ptr) std::cout before reset, ptr is: *ptr \n;ptr.reset();if (ptr) std::cout after reset, ptr is: *ptr \n;
}
//输出before reset, ptr is: 42