11:知识点1:理解变量的销毁与其内存的释放之间的关系:内置类型的指针在离开作用域时,本身会被销毁,但是其指向的内存空间什么都不会发生,必须以显式的delete进行释放空间。智能指针在离开作用域时,本身也会被销毁,并且计数器减一,当其计数器为0且只有一个智能指针指向该对象时,该对象的内存空间会被释放。如若用智能指针的get()函数得到的一个内置指针来初始化一个临时的智能指针,一旦该内置指针被释放,指向的内存也会被释放,原来的智能指针就会变成空指针
知识点2:永远不要用get初始化另一个智能指针或是给智能指针赋值
此题:利用P的get()函数得到的内置指针来初始化一个临时的智能指针,一旦调用结束,该临时指针被销毁,内置指针所指对象内存会被释放,使得p变为空悬指针
12:知识点1:将一个新的指针赋给shared_ptr:利用reset()函数,会更新计数。
此题:p为普通的内置指针指向一个动态内存,sp为智能指针指向一个动态内存
(a):合法,处理sp指针所指向内容,赋值的方式传递参数,处理完毕后内存不会被释放
(b):不合法,参数必须是智能指针int类型
(c):同上
(d):合法,处理完毕后内存会被释放
13:删除p之后,会导致p指向的内存被释放,此时sp就会变成空悬指针,在sp指针被销毁时,该块内存会被二次delete,执行后产生错误:double free
14:知识点1:如果在new和delete之间发生了异常,且异常未被捕获,则该内存就永远不会被释放!(非常危险!!!),而智能指针只要离开作用域,计数器减一,则随着智能指针被销毁,该块内存也会被释放,这就说明在实际使用过程中应使用shared_ptr来防止内存泄漏
知识点2:正确的使用智能指针:
1:不使用相同的内置指针值初始化多个智能指针
2:不delete get()返回的指针
3:不使用get()初始化或reset另一个只能指针
4:当你使用的智能指针管理的资源布氏new分配的内存,记住传递一个删除器
15:直接将删除器函数修改即可
[](connection *p){ disconnect *p; }16:知识点1:unique_ptr拥有其所指向的对象,属于一一对应关系,unique_ptr被销毁时,其对象也会被销毁,unique_ptr不支持拷贝和赋值,必须采用直接初始化的方式,当我们定义一个unique_ptr时,必须将其绑定到一个new返回的指针上
知识点2:可以使用release():放弃对指针的控制权,返回指针,并将其置为空,和reset():如果提供了内置指针q,令u指向这个对象,否则将u置空,将指针的所有权转移,但并没有释放内存
知识点3:在unique_ptr快要被销毁时,可以进行拷贝:返回unique_ptr指针,这是一种特殊的拷贝P473页
出现的问题:一一对应的关系,其指向的对象是其类的私有成员
error C2248: “std::unique_ptr<_Ty>::unique_ptr”: 无法访问 PRivate 成员(在“std::unique_ptr<_Ty>”类中声明)17:
(a):不合法,ix不是new返回的指针
(b):同上
(c):不合法,unique_ptr必须采用直接初始化
(d):不合法,同(a)
(e):合法
(f):合法,但是p5被销毁后,p2所指向的内存也会被销毁,使得p2成为空悬指针
18:release()函数的作用就是放弃对指针指向对象的控制权,但shared_ptr是多对一的关系,其他的智能指针仍然可以删除这个对象,所以这个函数的话对shared_ptr没意义
19:知识点1:weak_ptr:不控制所指向对象生命周期的智能指针,使用时必须进行判断对象是否存在
shared_ptr<int> u(new int(1024));weak_ptr<int> w_ptr(u);if (shared_ptr<int> u = w_ptr.lock()){ //....}若weak_ptr指向的内容存在,则lock()返回一个指向共享对象的shared_ptr,若无,则返回空shared_ptr
这样的类定义应该放在头文件中
class StrBlob{public: friend class StrBlobPtr;//声明friend StrBlobPtr begin(); StrBlobPtr end(); StrBlob();//默认构造函数 StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(il)){}///C++11新特性 StrBlob(string il):data(make_shared<vector<string>> (il)){}//另一构造函数 typedef vector<string>::size_type size_type;//定义类型别名,方便使用 //定义函数,返回大小 size_type size() const { return data->size(); } //判断vector<string>是否为空 bool empty() { return data->empty(); } //向vector<string>中加入元素 void pushback(const string &s) { data->push_back(s); } //访问函数,应首先调用check() string& front() { check(0,"front on empty StrBlob"); return data->front(); } string& back() { check(0,"back on empty StrBlob"); return data->back(); } void popback() { check(0,"pop_back on empty StrBlob"); data->pop_back(); }private: shared_ptr<vector<string>> data;//指向vector<string>的智能指针 void check(size_type i,const string &msg) const//若访问元素的大小大于data的size,输出错误信息 { if (i > data->size()) { throw out_of_range(msg);//抛出该out_of_range异常,表示不在范围之内 } }};class StrBlobPtr{public: StrBlobPtr():curr(0){}//构造函数,将curr设定为0 StrBlobPtr(StrBlob &a, size_t sz = 0):wptr(a.data),curr(sz){}//构造函数,将StrBlob的智能指针与此类中的weak_ptr绑定 string& deref() const { auto p =check(curr,"deference past end"); return (*p)[curr]; } StrBlobPtr& incr() { auto p =check(curr,"deference past end"); ++curr; return *this; }private: shared_ptr<vector<string>> check(size_t i,const string& msg) const//检查函数,返回一个vector<string>的智能指针 { auto ret = wptr.lock();//检查对象是否还存在 if(!ret) { throw runtime_error("未绑定"); } if (i >= ret->size()) { throw out_of_range(msg); } return ret; } weak_ptr<vector<string>> wptr;//定义弱智能指针 size_t curr;//设立游标,表示下标};StrBlobPtr StrBlob::begin(){ return StrBlobPtr(*this);}StrBlobPtr StrBlob::end(){ return StrBlobPtr(*this, data->size());}20:
#include<iostream> #include<string> #include<fstream>#include<list>#include<vector> #include<map> #include<set>#include<cctype>//ctype无法打开,包含tolower()函数和ispunct函数#include<algorithm>#include<utility>//保存pair的头文件#include<Chapter12.h>using namespace std;int main(int argc, char**argv) { ifstream in("1.txt"); string s; StrBlob blob; while (getline(in,s)) { blob.pushback(s); } for (StrBlobPtr pbeg(blob.begin()), pend(blob.end()); pbeg != pend; pbeg.incr()) cout << pbeg.deref() << std::endl; return 0;}
新闻热点
疑难解答
图片精选