前面已经有一切了c 语法是比较基础的c 以后博主会分析一些语法c 对于每个人来说,提高更高级的语法c 的理解
1)智能指针:
智能指针就是帮我们C 如果程序员管理动态分配的内存,它将帮助我们自动释放new从而产生内存!在我们知道内存分配后,我们必须释放它。当内存未释放时,内存会泄露,造成不良影响。
因此,智能指针是为了解决指针自动释放的问题。让我们来看看智能指针的相关内容。
一,auto_ptr
auto_ptr 是c 98定义的智能指针模板定义了管理指针的对象new 给这个对象一个获得(直接或间接)的地址。当对象过期时,将使用其分析函数delete 释放内存!
用法: 头文件: #include < memory > 用 法: auto_ptr<类型> 变量名(new 类型)
例子:
class Test { public: Test() { cout << "Test的构造函数..." << endl; } ~Test() { cout << "Test的析构函数..." << endl; }
int getDebug() { return this->debug; }
private: int debug = 20; };
int main(void) {
//Test *test = new Test;///智能指针没有定义,所以内存泄露,分析函数的内容不会打印
cout << "test->debug:" << test->getDebug() << endl; cout << "(*test).debug:" << (*test).getDebug() << endl;
return 0; }
智能指针的三个常用函数:
() 获取智能指针托管的指针地址
// 定义智能指针
auto_ptr<Test> test(new Test);
cout << "tmp->debug:" << tmp->getDebug() << endl;
但除非有特殊情况,否则我们通常不会这样使用,因为我们可以直接使用智能指针。
2.() 取消智能指针对动态内存的托管
// 定义智能指针
auto_ptr<Test> test(new Test);
Test *tmp2 = test.release(); // 取消智能指针对动态内存的托管
delete tmp2; // 之前分配的内存需要手动释放
也就是说,智能指针不再管理指针,而是由管理员管理!
3.r() 重置智能指针托管的内存地址,如果地址不一致,将被分析
// 定义智能指针
auto_ptr<Test> test(new Test);
test.reset(); // 释放智能指针托管的指针内存,并将其放置NULL
test.reset(new Test()); // 释放智能指针托管的指针内存,替换参数指针
reset函数将指出参数(不指定为NULL),与托管指针相比,如果地址不一致,则将对原托管指针进行分析,然后用参数指针代替。然后智能指针将托管参数指针。
不过,C 11后不建议使用auto_ptr,已使用unique_ptr替代品。这里就不详细说缺点了。有兴趣可以上网了解一下。
二.unique_ptr
unique_ptr 和 auto_ptr除了一些特殊的,用法几乎相同。
(
例子:
unique_ptr<string> p1(new string("I'm Li Ming!")); unique_ptr<string> p2(new string("I'm age 22.")); cout << "p1:" << p1.get() << endl; cout << "p2:" << p2.get() << endl;
cout << "p1 = p2 赋值后:" << endl; cout << "p1:" << p1.get() << endl; cout << "p2:" << p2.get() << endl;
vector<unique_ptr<string>> vec; unique_ptr<string> p3(new string("I'm P3")); unique_ptr<string> p4(new string("I'm P4"));
vec.push_back(std::move(p3)); vec.push_back(std::move(p4));
cout << "vec.at(0):" << *vec.at(0) << endl; cout << "vec[1]:" << *vec[1] << endl;
cout << "vec.at(0):" << *vec.at(0) << endl; cout << "vec[1]:" << *vec[1] << endl;
// 会自动调用delete [] 函数去释放内存
unique_ptr<int[]> array(new int[5]); // 支持这样的定义
除此之外,,unique_ptr的其余用法都与auto_ptr用法一致。
// unique_ptr<T> up; 空的unique_ptr,可以指向的对象 unique_ptr<Test> t1;
// unique_ptr<T> up1(new T()); 定义unique_ptr,同时的对象 unique_ptr<Test> t2(new Test);
// unique_ptr<T[]> up; 空的unique_ptr,可以指向[的数组对象 unique_ptr<int[]> t3;
// unique_ptr<T[]> up1(new T[]); 定义unique_ptr,同时指向的数组对象 unique_ptr<int[]> t4(new int[5]);
// unique_ptr<T, D> up(); 空的unique_ptr, unique_ptr<Test, DestructTest> t5;
// unique_ptr<T, D> up(new T()); 定义unique_ptr,同时指向类型为T的对象,接受一个D类型的删除器D,使用删除器D来释放内存 unique_ptr<Test, DestructTest> t6(new Test)
unique_ptr<Test> t7(new Test);
unique_ptr<Test> t8(new Test);
t7 = std::move(t8); // 必须使用移动语义,结果,t7的内存释放,t8的内存交给t7管理
t7->doSomething();
unique_ptr<Test> t9(new Test);
t9 = NULL;
t9 = nullptr;
t9.reset();//释放掉智能指针托管的指针内存,并将其置NULL
Test *t10 = t9.release();
t9.reset(new Test);
三.shared_ptr
用法:
shared_ptr<Person> sp1;
shared_ptr<Person> sp2(new Person(2));
// use_count():引用计数 cout << "sp1 use_count() = " << sp1.use_count() << endl;输入0 cout << "sp2 use_count() = " << sp2.use_count() << endl << endl;输出1
// 共享 sp1 = sp2;
cout << "sp1 use_count() = " << sp1.use_count() << endl;输入2 cout << "sp2 use_count() = " << sp2.use_count() << endl << endl;输出2
shared_ptr<Person> sp3(sp1); cout << "sp1 use_count() = " << sp1.use_count() << endl;输出3 cout << "sp2 use_count() = " << sp2.use_count() << endl;输出3 cout << "sp2 use_count() = " << sp3.use_count() << endl << endl;输出3
如上代码,sp1 = sp2; 和 shared_ptr< Person > sp3(sp1);就是在使用引用计数了。
sp1 = sp2; --> sp1和sp2共同托管同一个指针,所以他们的引用计数为2; shared_ptr< Person > sp3(sp1); --> sp1和sp2和sp3共同托管同一个指针,所以他们的引用计数为3;
2.几种
shared_ptr<Person> sp1;
Person *person1 = new Person(1);
sp1.reset(person1); // 托管person1
shared_ptr<Person> sp2(new Person(2));
shared_ptr<Person> sp3(sp1);
shared_ptr<Person[]> sp4;
shared_ptr<Person[]> sp5(new Person[5] { 3, 4, 5, 6, 7 });
shared_ptr<Person> sp6(NULL, DestructPerson());
shared_ptr<Person> sp7(new Person(8), DestructPerson());
3.初始化
方式一:1.构造函数
shared_ptr<int> up1(new int(10)); // int(10) 的引用计数为1
shared_ptr<int> up2(up1); // 使用智能指针up1构造up2, 此时int(10) 引用计数为2
2.方式二:使用make_shared 初始化对象,分配内存效率更高(推荐使用) make_shared函数的 用法:make_shared<类型>(构造类型对象需要的参数列表);
shared_ptr<int> up3 = make_shared<int>(2); // 多个参数以逗号','隔开,最多接受十个 shared_ptr<string> up4 = make_shared<string>("字符串"); shared_ptr<Person> up5 = make_shared<Person>(9);
4.赋值
shared_ptrr<int> up1(new int(10)); // int(10) 的引用计数为1 shared_ptr<int> up2(new int(11)); // int(11) 的引用计数为1 up1 = up2; // int(10) 的引用计数减1,计数归零内存释放,up2共享int(11)给up1, int(11)的引用计数为2,这种赋值方式是允许的哦
5.主动释放对象
shared_ptrr<int> up1(new int(10));
up1 = nullptr ; // int(10) 的引用计数减1,计数归零内存释放 // 或 up1 = NULL; // 作用同上
6.重置
p.reset() ; 将p重置为空指针,所管理对象引用计数 减1 p.reset(p1); 将p重置为p1(的值),p 管控的对象计数减1,p接管对p1指针的管控 p.reset(p1,d); 将p重置为p1(的值),p 管控的对象计数减1并使用d作为删除器 p1是一个指针!
7.交换
p1 和 p2 是智能指针
std::swap(p1,p2); // 交换p1 和p2 管理的对象,原对象的引用计数不变
p1.swap(p2); // 交换p1 和p2 管理的对象,原对象的引用计数不变
注意:
在必要的使用可以转换成共享指针 lock();
如:shared_ptr<Girl> sp_girl;
sp_girl = wpGirl_1.lock();
// 使用完之后,再将共享指针置NULL即可
sp_girl = NULL;
智能指针虽然使用起来很方便,但是要注意使用智能指针的一些陷阱,否则会造成严重的内存报错或者内存泄露等问题!
本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.