& && -> &
&& & -> &
& & -> &
&& && -> &&
void actualRun(int a) {
}
template <typename T>
void testPerfectForward(T &¶m) {
actualRun(param);
}
void testPerfectForwardMain() {
int a = 0;
testPerfectForward(a);
}
上述 T 为int &。 那么整个为 int & &&-> int &
回到完美转发,假设现在我需要转发a,那么注意一下实现完美转发需要这样写
template <typename T>
void testPerfectForward1(T &¶m) {
actualRun(std::forward(param));
}
forward大致实现原理
static_cast + &&
template <typename T>
T&& forwad(T ¶m) {
return static_cast<T&&>(param);
}
注意其实std::move底层实现也是 static_cast
#include
using namespace std;
void isnull(void *c){
cout << "void*c" << endl;
}
void isnull(int n){
cout << "int n" << endl;
}
void testNull1() {
isnull(0);
//isnull(NULL);//Call to 'isnull' is ambiguous
isnull((void*)NULL);
/*
int n
void*c
*/
}
1 . nullptr 是 nullptr_t 类型的右值常量,专用于初始化空类型指针。nullptr_t 是 C++11 新增加的数据类型,可称为“指针空值类型”。也就是说,nullpter 仅是该类型的一个实例对象(已经定义好,可以直接使用),如果需要我们完全定义出多个同 nullptr 完全一样的实例对象。
void testNull2() {
isnull(0);
//isnull(NULL);//Call to 'isnull' is ambiguous
isnull((void*)NULL);
isnull(nullptr);
/*
int n
void*c
void*c
*/
}
void testNullMain() {
// int *p = 0;
// int *q = NULL;
// testNull1(0);
// testNull1(NULL);
}
void deleteInt(int *p) {
delete []p;
}
void testSharedPtr () {
std::cout << "testSharePtr: " << endl;
//初始化空的shareptr,引用计数为0不是1
std::shared_ptr<int> p1;
std::shared_ptr<int> p2(nullptr);
std::shared_ptr<int> p3(new int(10));
std::shared_ptr<int> p4 = std::make_shared<int>(10);
//调用拷贝构造函数
std::shared_ptr<int> p5(p4); //或者 p4 = p3;
//调用移动构造函数
std::shared_ptr<int> p6(std::move(p4)); //或者p6 = std::move(p4)
//智能指针可以拷贝,给多个智能指针用,引用计数+1,但是普通指针,只能拷贝给一个智能指针
int *p = new int(1);
std::shared_ptr<int> pp1(p);
// std::shared_ptr pp2(p); //错误!!!!
// 在初始化 shared_ptr 智能指针时,还可以自定义所指堆内存的释放规则,这样当堆内存的引用计数为 0 时,会优先调用我们自定义的释放规则。在某些场景中,自定义释放规则是很有必要的,比如,对于申请的动态数组来说,share—_ptr指针默认的释放规则是不支持释放数组的,值呢个自定义对于的释放规则,如下:
//释放规则可以使用 C++11 标准中提供的 default_delete 模板类,我们也可以自定义释放规则:
std::shared_ptr<int> p10(new int[10], std::default_delete<int[]>());
std::shared_ptr<int> p11(new int[10], deleteInt);
std::shared_ptr<int> p12(new int[10], [](int *p){delete []p;});
std::shared_ptr<int> ppp1 = std::make_shared<int>(10);
std::shared_ptr<int> ppp2(ppp1);
std::cout << *ppp2 << endl;
cout<< ppp2.use_count()<<endl;
ppp1.reset();
if (p1) {
std::cout << "ppp1 is not null !"<< endl;
} else {
std::cout << "ppp1 is null !"<< endl;
}
std::cout << *ppp2 << endl;
cout<< ppp2.use_count()<<endl;
}
表 1 shared_ptr<T>模板类常用成员方法
成员方法名 功 能
operator=() 重载赋值号,使得同一类型的 shared_ptr 智能指针可以相互赋值。
operator*() 重载 * 号,获取当前 shared_ptr 智能指针对象指向的数据。
operator->() 重载 -> 号,当智能指针指向的数据类型为自定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。
swap() 交换 2 个相同类型 shared_ptr 智能指针的内容。
reset() 当函数没有实参时,该函数会使当前 shared_ptr 所指堆内存的引用计数减 1,同时将当前对象重置为一个空指针;当为函数传递一个新申请的堆内存时,则调用该函数的 shared_ptr 对象会获得该存储空间的所有权,并且引用计数的初始值为 1。
get() 获得 shared_ptr 对象内部包含的普通指针。
use_count() 返回同当前 shared_ptr 对象(包括它)指向相同的所有 shared_ptr 对象的数量。
unique() 判断当前 shared_ptr 对象指向的堆内存,是否不再有其它 shared_ptr 对象再指向它。
operator bool() 判断当前 shared_ptr 对象是否为空智能指针,如果是空指针,返回 false;反之,返回 true。
*/
unique_ptr 指针指向的堆内存无法同其它 unique_ptr 共享,也就是说,每个 unique_ptr 指针都独自拥有对其所指堆内存空间的所有权
void testUniqueptr() {
std::unique_ptr<int> p1(new int(3));
// std::unique_ptr p1(p2);
std::unique_ptr<int> p2(std::move(p1));
// 默认情况下,unique_ptr 指针采用 std::default_delete 方法释放堆内存。当然,我们也可以自定义符合实际场景的释放规则。值得一提的是,和 shared_ptr 指针不同,为 unique_ptr 自定义释放规则,只能采用函数对象的方式。例如:
struct myDel {
void operator()(int *p) {
delete p;
}
};
std::unique_ptr<int, myDel> p7(new int);
// std::unique_ptr p6(new int);
std::unique_ptr<int> p10(new int);
*p10 = 10;
//p10释放当前所指堆的所有权, 但该存储空间不会被销毁,转移给了p
int *p = p10.release();
std::unique_ptr<int> p11;
//中 p 表示一个普通指针,如果 p 为 nullptr,则当前 unique_ptr 也变成空指针;反之,则该函数会释放当前 unique_ptr 指针指向的堆内存(如果有),然后获取 p 所指堆内存的所有权(p 为 nullptr)。
p11.reset(p);
// int *p2 = p;
}
weak_ptr是为了配合shared_ptr而引入的一种智能指针,它不具有普通指针的行为,没有重载*和->两个操作符,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。
weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。
使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count()==0,但更快,表示被观测的资源 (也就是shared_ptr的管理的资源)已经不复存在。
weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr 获得一个可用的shared_ptr对象,从而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr。
#include
class Test: public std::enable_shared_from_this<Test>
{
public:
Test();
~Test();
std::shared_ptr<Test> getSharedFromThis(){return shared_from_this();}
}
在什么情况下要使类A继承enable_share_from_this?
使用场合:当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。
我们就使类A继承enable_share_from_this,然后通过其成员函数share_from_this()返回当指向自身的share_ptr。
以上有2个疑惑:
1.把当前类对象作为参数传给其他函数时,为什么要传递share_ptr呢?直接传递this指针不可以吗?
一个裸指针传递给调用者,谁也不知道调用者会干什么?假如调用者delete了该对象,而share_tr此时还指向该对象。
2.这样传递share_ptr可以吗?share_ptr
这样会造成2个非共享的share_ptr指向一个对象,最后造成2次析构该对象。
————————————————
引用链接:https://blog.csdn.net/zk3326312/article/details/79108690
http://c.biancheng.net/view/3730.html