当前位置: 首页 > news >正文

佛山网站运营十年乐云seo打代码做网站的软件

佛山网站运营十年乐云seo,打代码做网站的软件,重庆手机网站制作价格,保定厂家推荐信息流推广文章目录前言动态内存与智能指针shared_ptr类shared_ptr和unique_ptr都支持的操作shared_ptr独有的操作make_shared 函数shared_ptr的拷贝和赋值shared_ptr自动销毁所管理的对象shared_ptr还会自动释放相关联的内存程序使用动态内存出于以下原因直接管理内存使用new动态分配和初… 文章目录前言动态内存与智能指针shared_ptr类shared_ptr和unique_ptr都支持的操作shared_ptr独有的操作make_shared 函数shared_ptr的拷贝和赋值shared_ptr自动销毁所管理的对象shared_ptr还会自动释放相关联的内存程序使用动态内存出于以下原因直接管理内存使用new动态分配和初始化对象动态分配的const对象内存耗尽 定位new释放动态内存使用new和delete管理动态内存存在三个常见问题delete之后重置指针值智能指针和new对比shared_ptr和new结合使用定义和改变shared_ptr的其他方法不要混合使用智能指针和普通指针不要使用get初始化另一个智能指针或为智能指针赋值智能指针和异常使用自己定义的释放操作使用智能指针基本规范unique_ptrunique_ptr特有的操作release返回指针传递unique_ptr参数和返回unique_ptr向unique_ptr传递删除器weak_ptr动态数组new和数组释放动态数组智能指针和动态数组指向数组的unique_ptr连接两个字符串allocator类标准库allocator类及其算法allocator分配未构造的内存allocator算法前言 静态内存用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量。栈内存用来保存定义在函数内的非static对象。分配在静态或栈内存中的对象由编译器自动创建和销毁。对于栈对象仅在其定义的程序块运行时才存在static对象在使用之前分配在程序结束时销毁。 除了静态内存和栈内存每个程序还拥有一个内存池。这部分内存被称为自由空间或堆。程序用堆来存储动态分配的对象——即那些在程序运行时分配的对象。动态对象的生存期由程序来控制也就是说当动态对象不再使用时我们的代码必须显式地销毁它们。 动态内存与智能指针 动态内存的管理是通过一对运算符来完成的new在动态内存中为对象分配空间并返回一个指向该对象的指针delete接受一个动态对象的指针销毁该对象并释放与之关联的内存。 动态内存的使用很容易出现问题因为确保在正确的时间释放内存是及其困难的。忘记释放内存会产生内存泄漏在尚有指针引用内存的情况下我们就释放了内存会产生引用非法内存的指针。 新标准库提供了两种智能指针类型来管理动态对象它可以自动释放所指向的对象。shared_ptr允许多个指针指向同一个对象unique_ptr则“独占”所指向的对象。weak_ptr是一种弱引用指向shared_ptr所管理的对象这三种类型都定义在memory头文件中。 shared_ptr类 当我们创建一个智能指针时必须提供额外的信息——指针可以指向的类型。与vector一样我们在尖括号内给出类型之后是所定义的这种智能指针的名字 shared_ptrstringp1; shared_ptr可以指向string shared_ptrlistintp2; shared_ptr可以指向listint默认初始化的智能指针中保存着一个空指针。 shared_ptr和unique_ptr都支持的操作 shared_ptr独有的操作 make_shared 函数 p3指向一个值为42的int的智能指针 shared_ptrintp3 make_sharedint(42);p4指向一个值为88888的string的智能指针 shared_ptrstringp4 make_sharedstring(5,8);p5指向一个值为0的int的智能指针int的初始化值为0 shared_ptrintp5 make_sharedint();shared_ptr的拷贝和赋值 当进行拷贝或赋值操作时每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象。离开作用域计数器会递减赋值操作原指针计算器会递减赋值指向的指针计数器会递增。示例代码如下 auto p make_sharedint(42);//p指向的对象只有p一个引用者auto r make_sharedint(4);//p指向的对象只有p一个引用者auto r2(r);//p指向的对象只有p一个引用者cout p引用数量 p.use_count()endl;{auto q(p);//p和q指向相同对象此对象有两个引用者cout p引用数量 p.use_count() endl;cout p指向 *p endl;*q 10;cout p指向 *p endl;}cout 在赋值之前p引用数量 p.use_count() endl;cout 在赋值之前原r引用数量 r2.use_count() endl;r p;cout 在赋值之后原r引用数量 r2.use_count() endl;cout 在赋值之后p引用数量 p.use_count() endl;cout p指向 *p endl;输出结果 p引用数量1 p引用数量2 p指向42 p指向10 在赋值之前p引用数量1 在赋值之前原r引用数量2 在赋值之后原r引用数量1 在赋值之后p引用数量2 p指向10shared_ptr自动销毁所管理的对象 当指向一个对象的最后一个shared_ptr被销毁时shared_ptr类会通过析构函数自动销毁此对象。shared_ptr的析构函数会递减它所指向的对象的引用计数如果引用计数为0shared_ptr的析构函数就会销毁对象并释放它占用的内存。 shared_ptr还会自动释放相关联的内存 当动态对象不再被使用时shared_ptr会自动释放动态对象这一特性使得动态内存的使用变得非常容易。 假设现有一个Foo类示例代码 //factory返回一个shared_ptr指向一个动态分配的对象 shared_ptrFoo factory(T arg){return make_sharedFoo(arg); }void use_factory(T arg){shared_ptrFoopfactory(arg);//使用p }//p离开作用域它指向的内存会被自动释放//但如果有其他shared_ptr也指向这块内存则它就不会被释放 shared_ptrFoo use_factory2(T arg){shared_ptrFoopfactory(arg);//使用preturn p;//当我们返回p时引用计数进行了递增 }//p离开作用域它指向的内存不会被释放因此如果将shared_ptr存放于一个容器中而后不再需要全部元素而只使用其中一部分要记得用erase删除不再需要的那些元素。 程序使用动态内存出于以下原因 程序不知道自己需要使用多少对象 例如容器类程序不知道所需对象的准确类型程序需要在多个对象间共享数据 我们定义一个类它使用动态内存是为了让多个对象共享相同的底层数据。我们定义一个名为Blob的类保存一组元素。我们希望Blob对象的不同拷贝之间共享相同的元素即当我们拷贝一个Blob时原Blob对象及其拷贝应该引用相同的底层元素。 Blob类的定义如下 #ifndef __BLOB__ #define __BLOB__#includestring # includeiostream # includevector # includememory using namespace std;class Blob { public:typedef vectorstring::size_type size_type;Blob();Blob(initializer_liststringil);size_type size()const { return data-size(); }bool empty()const{return data-empty();}//添加和删除元素void push_back(const string t) { data-push_back(t); }void pop_back();//元素访问string front();string back();//获取元素shared_ptrvectorstring getData() { return data; }//修改元素void changeData(size_type i,string str) {(*data)[i] str;}private:shared_ptrvectorstringdata;void check(size_type i,const string msg)const; };Blob::Blob() :data(make_sharedvectorstring()){} Blob::Blob(initializer_liststringil) : data(make_sharedvectorstring(il)) {} void Blob::check(size_type i, const string msg)const {if (i data-size())throw out_of_range(msg); } string Blob::front() {check(0,front on empty Blob);return data-front(); } string Blob::back() {check(0, back on empty Blob);return data-back(); } void Blob::pop_back() {check(0, pop_back on empty Blob);data-pop_back(); } void print(ostream os,Blob b) {for (auto a : *(b.getData())) {os a ;}os endl; }#endif 对Blob进行测试代码如下 Blob b1{ a,an,the };cout b1的元素为;print(cout,b1);Blob b2(b1);cout b2的元素为;print(cout, b2);b2.changeData(0,hello);cout 对b2中的元素进行修改后 endl;cout b1的元素为;print(cout, b1);cout b2的元素为;print(cout, b2);输出结果 b1的元素为a an the b2的元素为a an the 对b2中的元素进行修改后 b1的元素为hello an the b2的元素为hello an the从输出结果我们可以看出Blob在多个对象间共享数据。当我们拷贝、赋值或销毁一个Blob对象时它的shared_ptr成员会被拷贝、赋值或销毁。 我们定 义的Blob与vector的区别 vectorstringv1; {vectorstringv2{a,an,the};v1v2;//从v2拷贝元素到v1中 }//v2被销毁其中的元素也被销毁 //v1有三个元素是原来v2元素的拷贝Blobstringb1; {Blobstringb2{a,an,the};b1b2;//b1和b2共享相同的元素 }//b2被销毁其中的元素不能销毁 //b1指向最初由b2创建的元素直接管理内存 C语言定义了两个运算符来分配和释放动态内存。运算符new分配内存delete释放new分配的内存。相对于智能指针使用这两个运算符管理内存非常容易出错。 使用new动态分配和初始化对象 在自由空间分配的内存是无名的因此new无法为其分配的对象命名而是返回一个指向该对象的指针。 例如 int *pi new int(1024); vectorint *pv new vectorint{1,2,3,4,5};如果我们提供了一个括号包围的初始化器就可以使用auto从此初始化器来推断我们想要分配的对象的类型。只有当括号中仅有单一初始化器时才可以使用auto auto p1 new auto(obj); //p1指向一个与obj类型相同的对象 auto p2 new auto(a,b,c); //错误括号中只能有单个初始化器动态分配的const对象 类似其他任何const对象一个动态分配的const对象必须进行初始化。 const int *pci new const int(1024);内存耗尽 定位new 虽然现代计算机通常都配备大容量内存但是自由空间被耗尽的情况还是有可能发生。一旦一个程序用光了它所有可用的内存new表达式就会失败。默认情况下如果new不能分配所要求的内存空间它会抛出一个类型为bad_alloc的异常。我们可以改变使用new的方式来阻止它抛出异常。我们称这种形式的new为定位new。 int *p1 new int;//如果分配失败new抛出std::bad_alloc int *p1 new (nothrow) int;//如果分配失败new返回一个空指针释放动态内存 我们通过delete表达式来将动态内存归还给系统。delete表达式接受一个指针指向我们想要释放的对象 delete p;与new类型类似delete表达式也执行两个动作销毁给定的指针指向的对象释放对应的内存。 我们传递给delete的指针必须指向动态分配的内存或者是一个空指针。释放一块并非new分配的内存或者将相同的指针值释放多次其行为是未定义的。 由内置指针而不是智能指针管理的动态内存在被显式释放前一直都会存在。 使用new和delete管理动态内存存在三个常见问题 忘记delete内存会导致“内存泄漏”问题因为这种内存永远不可能归还给自由空间了。使用已经释放掉的对象。同一块内存释放两次。当有两个指针指向相同的动态分配对象时可能发生这种错误。如果对其中一个指针进行了delete操作对象的内存就被归还给自由空间了。如果我们随后又delete第二个指针自由空间就可能被破坏。 delete之后重置指针值 当我们delete一个指针后指针值就变为无效了。虽然指针已经无效但在很多机器上指针仍然保存着已经释放了的动态内存的地址。在delete之后指针就变成了人们所说的空悬指针即指向一块曾经保存数据对象但现在已经无效的内存的指针。 未初始化指针的所有缺点空悬指针也都有。有一种方法可以避免空悬指针的问题在指针即将要离开其作用域之前释放掉它所关联的内存。如果我们需要保留指针可以在delete之后将nullptr赋予指针这样就清楚地指出指针不指向任何对象。 动态内存的一个基本问题是可能有多个指针指向相同的内存。在delete内存之后重置指针的方法只对这个指针有效对其他任何仍指向已释放的内存的指针是没有作用的以下代码重置p对q没有任何作用。 int *p(new int(42)); auto qp; //p和q指向相同的内存 delete p;//p和q均变为无效 pnullptr;//指出p不再绑定到任何对象智能指针和new对比 int *qnew int(42),*rnew int(100); rq; auto q2make_sharedint(42),r2make_sharedint(100); r2q2;以上代码new指针的两个问题 内存泄漏问题r和q都指向42的内存地址而r原来保存的地址——100的内存再无指针管理不能进行释放造成内存泄漏。空悬指针问题r和q指向同一个动态对象如果程序编写不当很容易产生释放了其中一个指针而继续使用另一个指针的问题。 智能指针的优势 将q2赋予r2赋值操作会将q2指向的对象地址赋予r2并将r2原来指向的对象的引用计数减1将q2指向的对象的引用计数加1这样前者的引用计数变为0其占用的内存空间会被释放不会造成内存泄漏。而后者的引用计数变为2也不会因为r2和q2之一的销毁而释放它的内存空间因此也不会造成空悬指针的问题。 shared_ptr和new结合使用 如果我们不出事后一个智能指针它就会被初始化为一个空指针。我们还可以用new返回的指针来初始化智能指针。接受指针参数的智能指针构造函数是explicit因此我们不能将一个内置指针隐式转换为一个智能指针必须使用直接初始化形式来初始化一个智能指针。 shared_ptrintp1new int(1024);//错误 shared_ptrintp2(new int(1024));//正确使用了直接初始化形式定义和改变shared_ptr的其他方法 不要混合使用智能指针和普通指针 void process(shared_ptrintptr){}shared_ptrint x(new int(1024));//引用计数为1 process(x); //正确拷贝x会递增它的引用计数在process中引用计数为2 int j*x;//正确引用计数为1void process(shared_ptrintptr){}int *x(new int(1024)); process(x); //错误不能将int*转换为shared_ptrint process(shared_ptrint(x));//正确但内存会被释放 int j*x;//未定义的x是一个空悬指针在该调用中我们将一个临时的shared_ptr传递给process当这个调用所在的表达式结束时这个临时对象就被销毁了。销毁这个临时变量会递减引用计数此时引用计数为0因此当临时变量被销毁时它所指向的内存会被释放但x继续指向已经释放的内存从而变成一个空悬指针如果试图使用x的值其行为是未定义的。 当将一个shared_ptr绑定到一个普通指针时我们就将内存的管理责任交给了这个shared_ptr。一旦这样做了我们就不应该再使用内置指针来访问shared_ptr所指向的内存了。 使用一个内置指针来访问一个智能指针所负责的对象是很危险的因为我们无法知道对象何时会被销毁。 不要使用get初始化另一个智能指针或为智能指针赋值 智能指针类型定义了一个名为get的函数它返回一个内置指针指向智能指针管理的对象。当我们需要向不能使用智能指针的代码传递一个内置指针时可用get。使用get返回的指针的代码不能delete此指针。 shared_ptrintp(new int(42));//p的引用计数为1int *q p.get();//正确但使用q时要注意不要让它管理的指针被释放p的引用计数仍然为1{process(shared_ptrint(q));}int foo *p;//错误此时p的引用计数为1但p指向的内存已经被释放了p成为类似空悬指针的shared_ptr在本例中p和q指向相同的内存由于它们是相互独立创建的因此各自的引用计数都是1。当q所在的程序块结束时q被销毁这会导致q所指向的内存被释放。从而q变成一个空悬指针当我们试图使用p时将发生未定义的行为。而且当p被销毁时这块内存会被第二次delete。 智能指针和异常 使用智能指针即使程序块过早结束智能指针类也能确保在内存不再需要时将其释放 void f(){shared_ptrintsp(new int(42));//分配一个新对象//这段代码抛出一个异常且在f中未被捕获 }//在函数结束时shared_ptr自动释放内存与之相对的如果使用内置指针管理内存且在new之后在对应的delete之前发生异常则内存不会被释放 void f(){int *ipnew int(42);//动态分配一个新对象//这段代码抛出一个异常且在f中未被捕获则内存不会被释放delete ip;//释放内存的代码 }使用自己定义的释放操作 现有以下类和函数 struct destination;//表示我们正在连接什么 struct connection;//使用连接所需的信息 connection connect(destination*);//打开连接的函数 void disconnect(connection);//关闭给定的连接代码一 void f(destination d){//获得一个连接connection c connect(d);//使用连接//如果我们在f退出前忘记调用disconnect就无法关闭c了 }代码二使用shared_ptr //定义删除器 void end_connection(connection *p){disconnect(*p);} //创建shared_ptr void f(destination d){//获得一个连接connection c connect(d);shared_ptrconnectionp(c,end_connection);//使用连接//当f退出时即使是由于异常而退出connection会被正确关闭 } 当p被销毁时它不会对自己保存的指针执行delete而是调用end_connection接下来end_connection会调用disconnect从而确保连接被正确关闭。如果f正常退出那么p的销毁会作为结束处理的一部分。如果发生了异常p同样会被销毁从而连接被正确关闭。 使用智能指针基本规范 不适用相同的内置指针值初始化或reset多个智能指针不delete get()返回的指针不适用get()初始化或reset另一个智能指针如果使用get()返回的指针记住当最后一个对应的智能指针销毁后你的指针就变为无效了如果你使用智能指针管理的资源不是new分配的内存记住传递给它一个删除器 unique_ptr 与shared_ptr不同某个时刻只能有一个unique_ptr指向一个给定对象与shared相同的操作在表中 unique_ptr特有的操作 由于一个 unique_ptr拥有它所指向的对象因此 unique_ptr不支持普通的拷贝或赋值操作 unique_ptrstringp1(new string(hello)); unique_ptrstringp2(p1);//错误不支持拷贝 unique_ptrstringp3; p3p1;//错误不支持赋值虽然我们不能拷贝或赋值unique_ptr但可以通过调用release或reset将指针的所有权从一个非constunique_ptr转移给另一个unique_ptr release返回指针 如果我们不用另一个智能指针来保存release返回的指针我们的程序就要负责资源的释放 p2.release();//错误p2不会释放内存而且我们丢失了指针 auto pp2.release();//正确但我们必须记得 delete p传递unique_ptr参数和返回unique_ptr 不能拷贝unique_ptr的规则有一个例外我们可以拷贝或赋值一个将要被销毁的unique_ptr。最常见的例子是从函数返回一个unique_ptr unique_ptrint clone(int p){return unique_ptrint(new int(p)); }还可以返回一个局部对象的拷贝 unique_ptrint clone(int p){unique_ptrintret(new int(p));//...return ret; }向unique_ptr传递删除器 类似shared_ptrunique_ptr默认情况下用delete释放它所指向的对象。与shared_ptr一样我们可以重载一个unique_ptr中默认的删除器。 对比shared_ptr的连接程序我们重写连接程序如下 //定义删除器 void end_connection(connection *p){disconnect(*p);} //创建shared_ptr void f(destination d){//获得一个连接connection c connect(d);unique_ptrconnection,decltype(end_connection)*p(c,end_connection);//使用连接//当f退出时即使是由于异常而退出connection会被正确关闭 }weak_ptr weak_ptr是一种不控制所指向对象生存期的智能指针它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁对象就会被释放。即使有weak_ptr指向对象对象也还是会被释放。 示例代码 auto p make_sharedint(42);auto q(p);auto p2(p);cout p.use_count(): p.use_count() endl;weak_ptrintwp(p);cout p.use_count(): p.use_count() endl;cout wp.use_count(): wp.use_count() endl;输出结果 p.use_count():3 p.use_count():3 wp.use_count():3由于对象可能不存在我们不能使用weak_ptr直接访问对象必须调用lock。次函数检查weak_ptr指向的对象是否仍存在。 if(shared_ptrintnpwp.lock()){ //如果np不为空则条件成立 //在if中np与p共享对象 }动态数组 new和数组 int *pia new int[10];//分配10个intpia指向第一个int分配一个数组会得到一个元素类型的指针。 我们还可以提供一个元素初始化器的花括号列表 释放动态数组 delete p;//p必须指向一个动态分配的对象或为空 delete [] p;//p必须指向一个动态分配的数组或为空 //数组中的元素按逆序进行销毁即最后一个元素首先被销毁 //然后是倒数第二个以此类推智能指针和动态数组 标准库提供了一个可以管理new分配的数组的unique_ptr版本。 unique_ptrint[]up(new int[10]); up.release();//自动用delete[]销毁其指针指向数组的unique_ptr 与unique_ptr不同shared_ptr不直接支持管理动态数组如果希望使用shared_ptr管理一个动态数组必须提供自己定义的删除器 shared_ptrintsp(new int[10],[](int *p){delete[]p;}); sp.reset();//使用我们提供的lambda释放数组它使用delete[]释放数组如果未提供删除器这段代码将是未定义的。默认情况下shared_ptr使用delete销毁它指向的对象。 连接两个字符串 代码 const char *c1 hello;const char *c2 world;char *r new char[strlen(c1) strlen(c2)1];strcpy(r,c1);strcat(r, c2);cout r endl;string s1 hello;string s2 world;strcpy(r,(s1s2).c_str());cout r endl;输出结果 helloworld helloworldallocator类 new有一些灵活性上的局限其中一方面表现在它将内存分配和对象构造组合在了一起这可能会导致不必要的浪费。 标准库allocator类定义在头文件memory中。它帮助我们将内存分配和对象构造分离开来。它提供一种类型感知的内存分配方法它分配的内存是原始的、未构造的。 标准库allocator类及其算法 allocator分配未构造的内存 还未构造对象的情况下就使用原始内存是错误的。 为了使用allocate返回的内存我们必须用construct构造对象。使用未构造的内存其行为是未定义的。 当我们用完对象后必须对每个构造的元素调用destroy来销毁它们。函数destroy接受一个指针对指向的对象执行析构函数。 allocator算法 类似copyuninitialized_copy返回递增后的目的位置迭代器因此一次uninitialized_copy调用会返回一个指针指向最后一个构造的元素之后的位置。
http://www.zqtcl.cn/news/193026/

相关文章:

  • 个人网站模板下载提供网站建设备案公司
  • 做网站需要会写代码6山东东营
  • 兼职刷客在哪个网站做网站搬家数据库配置
  • 做搬运的话哪个网站好网站模板建站
  • 建设个人信息网站wordpress 用户权限
  • 网站不显示域名解析错误怎么办公益网站设计
  • 怎么上传网站图片的链接手表网站排行榜
  • 网站推广方法100种百度排名规则
  • 上海专业网站建设公司站霸网络萝岗区网站建设推广
  • 做微商网站的公司永久免费crm管理系统
  • 网站开发的环境专业的建设网站
  • 公司网站建设知识注册网站备案
  • 营销型网站建设申请域名在域名做网站
  • 电商网站设计公司立找亿企邦山东德州网站建设哪家最好
  • 免费自建网站工具网站建设公司那个好
  • wordpress集成环境搭建短视频优化
  • 做网站一般把宽度做多少中国企业报集团官网
  • 什么软件可以建网站网站建设应该计入什么费用
  • 网站制作 手机版重庆网站建设mswzjs
  • 网站建设犀牛云品牌建设方案和思路
  • 网络管理系统的管理软件抖音优化推广
  • 昆山市有没有做网站设计的交互设计研究生
  • 本地网站asp iiswordpress 感染支付宝
  • 成都最专业做网站的wordpress升级500
  • 做网站首页图的规格网站建设的市场分析
  • a032网站模版自己建立网站怎么建
  • wordpress.商品厦门做网站优化价格
  • 学校网站建设源码视频生成链接网站
  • 江苏建设工程招投标网站wordpress 全部tags
  • 十堰网站建设有哪些公司wordpress删除摘要