C++ Primer笔记——lower/upper_bound、hash、make_shared、智能指针与new结合使用

目录

一.P389 关联容器的lower/upper_bound和equal_range函数

二.P396 标准库hash类型

三.P401 make_shared函数

四.P412 shared_ptr和new结合使用

(一).构造函数不支持隐式类型转换

(二).不要混合使用普通指针和智能指针

(三).不要使用get初始化另一个智能指针或赋值


一.P389 关联容器的lower/upper_bound和equal_range函数

成员函数 含义
lower_bound(k) 返回迭代器,指向第一个不小于k的元素
upper_bound(k) 返回迭代器,指向第一个大于k的元素
equal_bound(k) 返回pair,first到second为元素k的范围。不存在则first与second均为尾置迭代器

 以set举例:

set<int> st = { 1, 2, 3, 4, 4, 4, 5, 6, 7 };
auto it1 = st.lower_bound(4);
//set<int> st = { 1, 2, 3, 4, 4, 4, 5, 6, 7 };
//                         ^
//                        it1
auto it2 = st.upper_bound(4);
//set<int> st = { 1, 2, 3, 4, 4, 4, 5, 6, 7 };
//                                  ^
//                                 it2
auto it3 = st.equal_range(4);
//set<int> st = { 1, 2, 3, 4, 4, 4, 5, 6, 7 };
//                         ^        ^
//                       first     second

二.P396 标准库hash类型

hash是标准库提供的一种类,头文件<functional>。

hash重载了小括号,参数是内置类型、string、智能指针,返回值是对应生成的哈希值,返回类型是size_t。

通过使用小括号,即仿函数,获取参数对应的哈希值

使用方式如下:

shared_ptr<int> sp = make_shared<int>(4);
hash<shared_ptr<int>> hs;
cout << hs(sp);//得到智能指针对象的哈希值

三.P401 make_shared函数

在为智能指针开辟空间时,最好使用make_shared而不是通过new来分配内存

make_shared在动态内存中申请一个对象并初始化,返回shared_ptr对象

make_shared尖括号内是目标对象类型,传参要与目标的构造函数相同。

使用方式如下:

//开辟一个int空间,初始化为4
shared_ptr<int> sp = make_shared<int>(4);

四.P412 shared_ptr和new结合使用

(一).构造函数不支持隐式类型转换

众所周知,shared_ptr构造函数是explicit的,因此,不要希望通过通过赋值的形式完成初始化操作,那样会有隐式类型转换发生,而shared_ptr会报错。

shared_ptr<int> sp = new int(10);//错误
shared_ptr<int> sp(new int(10));//正确

同样的错误有可能会在函数返回值中出现,应该要格外小心。

shared_ptr<int> func() {
	return new int(10);//错误
	return shared_ptr<int>(new int(10));//正确
}

(二).不要混合使用普通指针和智能指针

混合使用最大的问题是可能造成悬空指针。

比如下列代码:

void func(shared_ptr<int> sp) {
    //...
}

int main()
{
	int* p = new int(10);
	cout << *p;
	func(shared_ptr<int>(p));
	cout << *p;
	return 0;

}

在这段代码里,当func函数结束时,sp会调用析构函数,因为只有sp一个智能指针指向p空间,因此p指针空间会被释放,当回到main函数时,p已经指向一块被释放的空间,即悬空指针,如果继续使用p,其行为是未定义的。

因此,如果使用的是shared_ptr,那请确保空间没有被普通指针所指,因为我们无法知道对象何时会被释放。

(三).不要使用get初始化另一个智能指针或赋值

智能指针的get函数能返回一个内置指针,与智能指针所指对象相同。

如果使用get函数为另一个智能指针初始化或赋值,那可能发生二次释放。 

以下面代码为例:

shared_ptr<int> sp(new int(10));
int* p = sp.get();
shared_ptr<int> sp2(p);

通过get函数让普通指针p与智能指针sp指向同一片空间。在将空间让另一个智能指针sp2指向。

当函数结束时,sp2会先析构,因为sp2是独立创建的(sp2并不知道空间来自智能指针sp),因此引用计数为1,会直接释放该空间。当sp析构时,引用计数也为1,会发生二次释放。

 比如书中练习题12.13就是会在程序结束时崩溃,因为sp发生了二次释放:

auto sp = make_shared<int>();
auto p = sp.get();
delete p;//释放空间
//sp析构,空间二次释放

综合来讲,使用shared_ptr时,确保自己的空间来自智能指针或make_shared。同时如果使用get函数,那么请不要将返回值用于另一个智能指针。


如有错误,敬请斧正

猜你喜欢

转载自blog.csdn.net/weixin_61857742/article/details/128442297