c++部分内容(来源于牛客,自己增加)

C++基础

1. 虚函数

2. 指针的理解

3. malloc和new的基本概念以及区别

csdn资料
一、属性方面,malloc是库函数,需要头文件支持,new是运算符,需要编译器支持。
二、参数方面,new无需指定内存大小,编译器会自行计算;malloc需要指定内存大小。而且new会调用构造函数。
三、处理数组方面,new使用new[],并使用delete[]进行释放,malloc需要手动定义数组大小,并用free释放内存。
四、返回类型,malloc返回值是void*指针,使用前需要显式地指定为需要的指针类型。new分配成功返回的是对象类型指针,与对象严格匹配,无类型转换,所以new是符合类型安全性操作符。
五、内存分配方面,new内存分配失败时,抛出bad_alloc异常,malloc分配内存失败时返回NULL。
六、自定义类型方面,new会先调用operator new函数,申请足够的内存,然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete就是反着来,先调用析构函数,然后operator delete函数释放内存。malloc是库函数,只能动态地申请和释放内存,无法强制要求其做自定义类型对象构造和析构函数。
七、new可以重载,malloc不可以
八、new在自由储存区分配内存,malloc在堆上分配内存。
九、内存泄漏方面,内存泄漏对于new和malloc都能检测出来,new可以明确指出是哪个文件的哪一行,但是malloc不可以明确指出是哪个文件的哪一行。
十、效率方面,new是关键字,malloc是库函数,new效率更高。
图1

4. 智能指针,弱指针作用

5. *p++的间隔

6. 指针为NULL,访问会怎样

简单说一下,c的NULL是宏定义,为void*,而cpp的NULL宏定义为0。cpp常用nullptr来给指针赋初值。nullptr的值为void*。

可以给指针赋初始值为NULL,但是不可以访问。内存地址为0的区域是用户应用程序访问的禁区,一旦访问就会段错误。

7. const int *p和int * const p的区别

常量指针和指针常量。前者本质为指针,只是指针指向内存区域里存放的数据为常量,所以常量指针:指向的区域可以更改,指向的内容不可以更改;后者本质为常量,只是常量里装的是指针,所以指针指向不能改,指向的内容可以更改。

8. C++ join detach

pthread_join()是在父线程中调用,等子线程运行完后通知子线程,然后父线程回收子线程资源。pthread_detach()是在子线程中调用,是子线程脱离父线程,子线程运行完后由系统回收资源。

9. C++ 11新特性

内容参考于csdn
一、cpp新特性
cpp新特性主要包括包含语法改进和标准库扩充两个方面,主要包括以下11点
1、语法的改进
1)统一的初始化方法
在 cpp11 中,可以直接在变量名后面跟上初始化列表,来进行对象的初始化
2)成员变量默认初始化
3)auto关键字用于定义变量,编译器可以自动判断的类型(前提:定义一个变量时对其进行初始化)
4)decltype 求表达式的类型
5)智能指针 shared_ptr

和 unique_ptr、weak_ptr 不同之处在于,多个 shared_ptr 智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)
6)空指针 nullptr(原来NULL)
7)基于范围的for循环
8)右值引用和move语义

  • 右值引用
//左值引用
int num = 10;
int &b = num;  //正确
int &c = 10;   //错误,在cpp98/03标准中,无法为右值添加引用

实际开发中可能需要对右值进行修改(实现移动语义时就需要),显然左值引用的方式是行不通的。为此,cpp11 标准新引入了另一种引用方式,称为右值引用,用 “&&” 表示。

int num = 10;
//int && a = num;  //右值引用不能初始化为左值
int && a = 10;
  • move语义

在cpp11中,标准库在中提供了一个有用的函数std::move,std::move()函数并不能移动任何东西,它唯一的功能是将一个左值引用强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义。从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue);

move( arg ) //其中,arg 表示指定的左值对象。该函数会返回 arg 对象的右值形式。

2、标准模板库的扩充(往STL里面添加了一些模板类,比较好用)
9)无序容器(哈希表)
用法和功能同map一模一样,区别在于哈希表的效率更高
10)正则表达式
可以认为正则表达式实质上是一个字符串,该字符串描述了一种特定模式的字符串
11)Lambda表达式(匿名函数)
lambda表达式是一个匿名函数,用于定义并创建匿名的函数对象,以简化编程工作。举个例子:

 vector<int> vec;
 sort(vec.begin(), vec.end(), cmp); // 旧式
 sort(vec.begin(), vec.end(), [](int a, int b) -> bool { return a < b; });   // Lambda表达式

声明lambda表达式:

[capture list] (params list) mutable exception-> return type { function body }
  • capture list:捕获外部变量列表
  • params list:形参列表
  • mutable指示符:用来说用是否可以修改捕获的变量
  • exception:异常设定
  • return type:返回类型
  • function body:函数体

二、智能指针

为什么要使用智能指针

智能指针的作用是管理一个指针,因为存在申请的空间在函数结束时忘记释放,造成内存泄漏的情况。使用智能指针可以很大程度上避免这个问题,因为智能指针就是一个类,当超出了类的作用域时,类会自动调用析构函数,自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间
智能指针的作用:处理内存泄漏问题和空悬指针问题。

cpp中的智能指针有4种,分别为:shared_ptr、unique_ptr、weak_ptr、auto_ptr,其中auto_ptr被cpp11弃用。

  • 对于shared_ptr,可解决资源忘记释放的内存泄漏问题,及悬空指针问题。
    *shared_ptr实现共享式拥有的概念,多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。

  • 对于unique_ptr,对象对其有唯一所有权。
    unique_ptr实现独占式拥有的概念,同一时间只能有一个智能指针可以指向该对象,它对于避免资源泄露,因为无法进行拷贝构造和拷贝赋值,但是可以进行移动构造和移动赋值。

  • 对于weak_ptr,和 shared_ptr 搭配,不会增加引用计数,用于避免循环引用(比如 a 对象持有 b 对象,b 对象持有 a 对象),这样必然会导致内存泄露。
    解决shared_ptr相互引用时,两个指针的引用计数永远不会下降为0,从而导致死锁问题。而weak_ptr是对对象的一种弱引用,可以绑定到shared_ptr,但不会增加对象的引用计数

  • 对于auto_ptr,实现独占式拥有的概念,同一时间只能有一个智能指针可以指向该对象;但auto_ptr在cpp11中被摒弃,其主要问题在于:
    1)对象所有权的转移,比如在函数传参过程中,对象所有权不会返还,从而存在潜在的内存崩溃问题;
    2)不能指向数组,也不能作为STL容器的成员

10. 匿名函数

匿名函数lambada表达式,就是没有名字的函数。最常见的匿名函数是[](){}。它没有参数也没有返回值。在匿名函数中,[]里面用来捕获函数外部的变量,而()里面就是匿名函数的参数,{}里面就是函数的执行代码。

概念:cpp11提供了类似与Python的lambda表达式的方式,称为匿名函数,其好处是:使用匿名函数,可以免去函数的声明和定义。这样匿名函数仅在调用函数的时候才会创建函数对象,而调用结束后立即释放,所以匿名函数比非匿名函数更节省空间。

Lambda在STL中使用,书写上带来极大的方便。
捕获capture: //类似于函数名,是匿名函数的触发条件

[] //未定义变量.试图在Lambda内使用任何外部变量都是错误的.
[x, &y] //x 按值捕获, y 按引用捕获.
[&] //用到的任何外部变量都隐式按引用捕获
[=] //用到的任何外部变量都隐式按值捕获
[&, x] //x显式地按值捕获. 其它变量按引用捕获
[=, &z] //z按引用捕获. 其它变量按值捕获

parameters: //参数
return-type: //返回值
body: //函数体
例子:

[](int x, int y) { return x + y; } // 隐式返回类型
[](int& x) { ++x; }   // 没有return语句 -> lambda 函数的返回类型是'void'
[]() { ++global_x; }  // 没有参数,仅访问某个全局变量
[]{ ++global_x; }     // 与上一个相同,省略了()

11. 类内默认的函数

6种:无参构造函数,析构函数,拷贝构造函数(浅拷贝的)、赋值运算符重载函数、const成员、取地址及const取地址操作符重载。

12. 什么时候重载拷贝构造函数

13. 深浅拷贝

浅拷贝就是直接用等号连接的赋值操作,一般类中不涉及内存开辟的话,浅拷贝可以使用。深拷贝需要重写拷贝构造函数。浅拷贝就是创建一个新的指针来指向对应的内容。深拷贝是新开辟一块区域,然后向指定的内容存入这块区域,然后用一个新的指针指向这块区域。

浅拷贝只是对指针的拷贝,浅拷贝后两个指针指向同一个内存空间;深拷贝不仅对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

当拷贝一个基类指针到派生类时,如果调用系统默认的拷贝构造函数,这时只是对指针进行拷贝,两个指针指向同一个地址,这就会导致指针被分配了一次内存,但内存被释放了两次(两次调用析构函数),造成程序崩溃。

对于类中开辟了内存空间的情况,必须重写拷贝构造函数以实现深拷贝,否则会出现一块内存区域被重复释放多次的错误。

14. stl容器底层实现

15. unordered_map和map区别

16. 锁的作用

17. lock_guard的用法

操作系统

1. 进程和线程区别

2. 一个线程崩溃了对其他线程有什么影响

数据结构

1. 红黑树基础概念,特性,根节点是什么颜色,可以有连续两个红节点吗

算法题

1. 获取链表倒数第三个节点(双指针)

C++中的智能指针

内容参考自csdn1csdn2

前言

C++ STL(Standard Template Library)一共提供了四种指针:auto_ptr、unique_ptr、shared_ptr 和 weak_ptr,其中auto_ptr是cpp98提供的,cpp11 已将其摒弃,并提出了 unique_ptr 替代 auto_ptr。

虽然 auto_ptr 已被摒弃,但在实际项目中仍可使用,但建议使用更加安全的 unique_ptr。cpp98中只有一种智能指针auto_ptr,这个智能指针实际上是一个封装好的类,方便管理指针,使用构造函数来生成指针,使用析构函数来释放指针,避免内存泄漏。但是auto_ptr有漏洞,基于此,提出了三种新指针,unique_ptr限制了指针的所有权,只有一个对象所持有;shared_ptr在指针管理类中新增一个计数值,来记录指针所引用对象的个数,当计数值为0时就释放指针;weak_ptr智能指针没有没有重载 operator* 和 operator->,他常作为shared_ptr的辅助指针,用于监测shared_ptr的引用计数值。

1、unique_ptr

它持有对对象的独有权——两个unique_ptr 不能指向一个对象,即 unique_ptr 不共享它所管理的对象。它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL)算法。只能移动 unique_ptr,即对资源管理权限可以实现转移。这意味着,内存资源所有权可以转移到另一个 unique_ptr,并且原始 unique_ptr 不再拥有此资源。

unique_ptr 与原始指针一样有效,并可用于 STL 容器。将 unique_ptr 实例添加到 STL 容器运行效率很高,因为通过 unique_ptr 的移动构造函数,不再需要进行复制操作。

独占的指针,只可以自己使用,它指向的对象只可以他一个人使用,可以使用move将使用权转移,如:

#include <iostream>
#include <memory>
using namespace std;
int main(){
    auto ptr1=make_unique<string> ("12345");
    cout<<*ptr1<<endl;
    auto ptr2=std::move(ptr1);
    // cout<<*ptr1<<endl;
    cout<<*ptr2<<endl;
    return 0;
}
//输出结果:
//12345
//12345

创建智能指针的方法:通过构造函数指定、通过 reset 方法重新指定、通过 release 方法释放所有权、通过移动语义转移所有权(move),unique_ptr 还可能没有对象,这种情况被称为 empty。

#include <iostream>
#include <memory>
using namespace std;
int main(){
    unique_ptr<int> p1;
    p1.reset(new int(123));
    cout<<*p1<<endl;
    unique_ptr<int> p2(new int(1234));
    cout<<*p2<<endl;
    int *p3=p1.release();
    cout<<*p3<<endl;
    unique_ptr<int> p4=move(p2);
    cout<<*p4<<endl;
 
    return 0;
}
// 123
// 1234
// 123
// 1234

2、auto_ptr

引入问题:

auto_ptr< string> p1(new string ("string1");
auto_ptr<string> p2;
p2=p1;

如果上面的指针是普通的指针,那么就会面临一个问题,就是delete的时候会删除有两次,解决方案有多种:

1、重载复制运算符,将其定义为深复制,这样他们俩就会指向不同的地方,缺点是会浪费空间。

2、建立所有全概念。将指针定义为只可以有一个对象拥有,赋值运算符直接将所有权转移。这就是用于 auto_ptr 和 unique_ptr 的策略,但 unique_ptr 的策略更严格。

3、创建智能更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。例如,赋值时,计数将加 1,而指针过期时,计数将减 1,。当减为 0 时才调用 delete。这是 shared_ptr 采用的策略。

3、shared_ptr

shared_ptr 是一个标准的共享所有权的智能指针,允许多个指针指向同一个对象,定义在 memory 文件中,命名空间为 std。shared_ptr 利用引用计数的方式实现了对所管理的对象的所有权的分享,即允许多个 shared_ptr 共同管理同一个对象。像 shared_ptr 这种智能指针,《Effective cpp》称之为“引用计数型智能指针”(reference-counting smart pointer,RCSP)。

shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针,当然这需要额外的开销:
(1)shared_ptr 对象除了包括一个所拥有对象的指针外,还必须包括一个引用计数代理对象的指针;
(2)时间上的开销主要在初始化和拷贝操作上, * 和 -> 操作符重载的开销跟 auto_ptr 是一样;
(3)开销并不是我们不使用 shared_ptr 的理由,,永远不要进行不成熟的优化,直到性能分析器告诉你这一点。

可以使用辅助类来实现该智能指针,它的具体做法如下:
(a)当创建智能指针类的新对象时,初始化指针,并将引用计数设置为1;
(b)当能智能指针类对象作为另一个对象的副本时,拷贝构造函数复制副本的指向辅助类对象的指针,并增加辅助类对象对基础类对象的引用计数(加1);
(c)使用赋值操作符对一个智能指针类对象进行赋值时,处理复杂一点:先使左操作数的引用计数减 1(为何减 1:因为指针已经指向别的地方),如果减1后引用计数为 0,则释放指针所指对象内存。然后增加右操作数所指对象的引用计数(为何增加:因为此时做操作数指向对象即右操作数指向对象);
(d)完成析构函数:调用析构函数时,析构函数先使引用计数减 1,如果减至 0 则 delete 对象。
接口:

class Point {
private:
    int x, y;
public:
    Point(int xVal = 0, int yVal = 0) :x(xVal), y(yVal) {}
    int getX() const { return x; }
    int getY() const { return y; }
    void setX(int xVal) { x = xVal; }
    void setY(int yVal) { y = yVal; }
};

实现:

class SmartPtr {
public:
	//构造函数
	SmartPtr() { rp = nullptr; }
	SmartPtr(Point *ptr):rp(new RefPtr(ptr)) {}
	SmartPtr(const SmartPtr &sp):rp(sp.rp) { 
		++rp->count;
		cout << "in copy constructor" <<endl;
	}
	
	// 重载赋值运算符
	SmartPtr& operator=(const SmartPtr& rhs) {
		++rhs.rp->count;
		if (rp != nullptr && --rp->count == 0) {
			delete rp;
		}
		rp = rhs.rp;
		cout << "in assignment operator" << endl;
		return *this;
	}
	
	// 重载->操作符
	Point* operator->() {
		return rp->p;
	}
	
	// 重载*操作符
	Point& operator*() {
		return *(rp->p);
	}
 
	~SmartPtr() {
		if (--rp->count == 0) delete rp;
		else cout << "还有" << rp->count << "个指针指向基础对象" << endl;
	}
 
private:
	RefPtr* rp;
};

4、weak_ptr

weak_ptr 被设计为与 shared_ptr 共同工作,可以从一个 shared_ptr 或者另一个 weak_ptr 对象构造而来。weak_ptr 是为了配合 shared_ptr 而引入的一种智能指针,它更像是 shared_ptr 的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载 operator* 和 operator-> ,因此取名为 weak,表明其是功能较弱的智能指针。*它的最大作用在于协助 shared_ptr 工作,可获得资源的观测权,像旁观者那样观测资源的使用情况。观察者意味着 weak_ptr 只对 shared_ptr 进行引用,而不改变其引用计数,当被观察的 shared_ptr 失效后,相应的 weak_ptr 也相应失效。

解决循环引用的问题,用法:

weak_ptr<T> w;	 	//创建空 weak_ptr,可以指向类型为 T 的对象
weak_ptr<T> w(sp);	//与 shared_ptr 指向相同的对象,shared_ptr 引用计数不变。T必须能转换为 sp 指向的类型
w=p;				//p 可以是 shared_ptr 或 weak_ptr,赋值后 w 与 p 共享对象
w.reset();			//将 w 置空
w.use_count();		//返回与 w 共享对象的 shared_ptr 的数量
w.expired();		//若 w.use_count() 为 0,返回 true,否则返回 false
w.lock();			//如果 expired() 为 true,返回一个空 shared_ptr,否则返回非空 shared_ptr

weak_ptr 对象引用资源时不会增加引用计数,但是它能够通过 lock() 方法来判断它所管理的资源是否被释放。

weak_ptr指针的作用

现在要说的问题是,weak_ptr 到底有什么作用呢?从上面那个例子看来,似乎没有任何作用。其实 weak_ptr 可用于打破循环引用。引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象。一个简单的例子如下:

#include <iostream>
#include <memory>
  
class Woman;  
class Man {
private:  
    //std::weak_ptr<Woman> _wife;  
    std::shared_ptr<Woman> _wife;  
public:  
    void setWife(std::shared_ptr<Woman> woman) {  
        _wife = woman;  
    }  
  
    void doSomthing() {  
        if(_wife.lock()){}  
    }  
  
    ~Man() {
        std::cout << "kill man\n";  
    }  
};  
  
class Woman {  
private:  
    //std::weak_ptr<Man> _husband;  
    std::shared_ptr<Man> _husband;  
public:  
    void setHusband(std::shared_ptr<Man> man) {  
        _husband = man;  
    }  
    ~Woman() {  
        std::cout <<"kill woman\n";  
    }  
};

int main(int argc, char** argv) {  
    std::shared_ptr<Man> m(new Man());  
    std::shared_ptr<Woman> w(new Woman());  
    if(m && w) {  
        m->setWife(w);  
        w->setHusband(m);  
    }  
    return 0;  
}

在 Man 类内部会引用一个 Woman,Woman 类内部也引用一个 Man。当一个 man 和一个 woman 是夫妻的时候,他们直接就存在了相互引用问题。man 内部有个用于管理wife生命期的 shared_ptr 变量,也就是说 wife 必定是在 husband 去世之后才能去世。同样的,woman 内部也有一个管理 husband 生命期的 shared_ptr 变量,也就是说 husband 必须在 wife 去世之后才能去世。这就是循环引用存在的问题:husband 的生命期由 wife 的生命期决定,wife 的生命期由 husband 的生命期决定,最后两人都死不掉,违反了自然规律,导致了内存泄漏。

一般来讲,解除这种循环引用有下面三种可行的方法:
(1)当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
(2)当 parent 的生存期超过 children 的生存期的时候,children 改为使用一个普通指针指向 parent。
(3)使用弱引用的智能指针打破这种循环引用。
虽然这三种方法都可行,但方法 1 和方法 2 都需要程序员手动控制,麻烦且容易出错。这里主要介绍一下第三种方法,使用弱引用的智能指针std:weak_ptr 来打破循环引用。

weak_ptr 对象引用资源时不会增加引用计数,但是它能够通过 lock() 方法来判断它所管理的资源是否被释放。做法就是上面的代码注释的地方取消注释,取消 Woman 类或者 Man 类的任意一个即可,也可同时取消注释,全部换成弱引用 weak_ptr

另外很自然地一个问题是:既然 weak_ptr 不增加资源的引用计数,那么在使用 weak_ptr 对象的时候,资源被突然释放了怎么办呢?不用担心,因为不能直接通过 weak_ptr 来访问资源。那么如何通过 weak_ptr 来间接访问资源呢?答案是在需要访问资源的时候 weak_ptr 为你生成一个shared_ptr,shared_ptr 能够保证在 shared_ptr 没有被释放之前,其所管理的资源是不会被释放的。创建 shared_ptr 的方法就是 lock() 成员函数。

注意: shared_ptr 实现了 operator bool() const 方法来判断被管理的资源是否已被释放。

5、如何选择智能指针

上文简单地介绍了 cpp STL 的四种智能指针。当然,除了 STL 的智能指针,cpp 准标准库 Boost 的智能指针,比如 boost::scoped_ptr、boost::shared_array、boost::intrusive_ptr 也可在实践中使用,但这里不做进一步介绍,有兴趣的读者可以参考:cpp 智能指针详解

在了解 STL 的四种智能指针后,大家可能会想另一个问题:在实际应用中,应使用哪种智能指针呢?

下面给出几个使用指南。
(1)如果程序要使用多个指向同一个对象的指针,应选择 shared_ptr。这样的情况包括:

将指针作为参数或者函数的返回值进行传递的话,应该使用 shared_ptr;
两个对象都包含指向第三个对象的指针,此时应该使用 shared_ptr 来管理第三个对象;
STL 容器包含指针。很多 STL 算法都支持复制和赋值操作,这些操作可用于 shared_ptr,但不能用于 unique_ptr(编译器发出 warning)和 auto_ptr(行为不确定)。如果你的编译器没有提供 shared_ptr,可使用 Boost 库提供的 shared_ptr。
(2)如果程序不需要多个指向同一个对象的指针,则可使用 unique_ptr。如果函数使用 new 分配内存,并返还指向该内存的指针,将其返回类型声明为 unique_ptr 是不错的选择。这样,所有权转让给接受返回值的 unique_ptr,而该智能指针将负责调用 delete。可将 unique_ptr 存储到 STL 容器中,只要对容器元素不使用拷贝操作的算法即可(如 sort())。例如,可在程序中使用类似于下面的代码段。

unique_ptr<int> make_int(int n) {
    return unique_ptr<int>(new int(n));
}

void show(unique_ptr<int>& p1) {
    cout << *p1 << ' ';
}

int main() {
	//...
    vector<unique_ptr<int>> vp(size);
    for(int i = 0; i < vp.size(); i++) {
		vp[i] = make_int(rand() % 1000);       // copy temporary unique_ptr
	}
    vp.push_back(make_int(rand() % 1000));     // ok because arg is temporary
    for_each(vp.begin(), vp.end(), show);      // use for_each()
	//...
}

其中 push_back 调用没有问题,因为它返回一个临时 unique_ptr,该 unique_ptr 被赋给 vp 中的一个 unique_ptr。另外,如果按值而不是按引用给 show() 传递对象,for_each() 将非法,因为这将导致使用一个来自 vp 的非临时 unique_ptr 初始化 pi,而这是不允许的。前面说过,编译器将发现错误使用 unique_ptr 的企图。

在 unique_ptr 为右值时,可将其赋给 shared_ptr,这与将一个 unique_ptr 赋给另一个 unique_ptr 需要满足的条件相同,即 unique_ptr 必须是一个临时对象。与前面一样,在下面的代码中,make_int() 的返回类型为 unique_ptr:

unique_ptr<int> pup(make_int(rand() % 1000));		// ok
shared_ptr<int> spp(pup);										// not allowed, pup as lvalue
shared_ptr<int> spr(make_int(rand() % 1000));    	// ok

模板 shared_ptr 包含一个显式构造函数,可用于将右值 unique_ptr 转换为 shared_ptr。shared_ptr 将接管原来归 unique_ptr 所有的对象。

在满足 unique_ptr 要求的条件时,也可使用 auto_ptr,但 unique_ptr 是更好的选择。如果你的编译器没有unique_ptr,可考虑使用 Boost 库提供的 scoped_ptr,它与 unique_ptr 类似。
(3)虽然说在满足 unique_ptr 要求的条件时,使用 auto_ptr 也可以完成对内存资源的管理,但是因为 auto_ ptr 不够安全,不提倡使用,即任何情况下都不应该使用 auto_ptr。
(4)为了解决 shared_ptr 的循环引用问题,我们可以祭出 weak_ptr。
(5)在局部作用域(例如函数内部或类内部),且不需要将指针作为参数或返回值进行传递的情况下,如果对性能要求严格,使用 scoped_ptr 的开销较 shared_ptr 会小一些。scoped_ptr正如其名,是一个局部指针。

6、auto_ptr存在的问题

尽可能不要把auto_ptr设置为全局指针;除非自己知道后果,否则不要把auto_ptr赋值给同类型的另一个智能指针。

在某些应用场景下,拷贝构造函数的意义不明确,同理赋值语句也是这个道理,意义同样不明确,因为C11标准之前并不存在移动赋值和移动构造的概念,还有就是之前谈到的一个对象和一组对象的问题,对于自定义类型而言,auto_ptr的析构函数仅能够析构一个对象,不能够处理一组对象的情况,这些都是尚未解决的问题。

r 也可以完成对内存资源的管理,但是因为 auto_ ptr 不够安全,不提倡使用,即任何情况下都不应该使用 auto_ptr。
(4)为了解决 shared_ptr 的循环引用问题,我们可以祭出 weak_ptr。
(5)在局部作用域(例如函数内部或类内部),且不需要将指针作为参数或返回值进行传递的情况下,如果对性能要求严格,使用 scoped_ptr 的开销较 shared_ptr 会小一些。scoped_ptr正如其名,是一个局部指针。

6、auto_ptr存在的问题

尽可能不要把auto_ptr设置为全局指针;除非自己知道后果,否则不要把auto_ptr赋值给同类型的另一个智能指针。

在某些应用场景下,拷贝构造函数的意义不明确,同理赋值语句也是这个道理,意义同样不明确,因为C11标准之前并不存在移动赋值和移动构造的概念,还有就是之前谈到的一个对象和一组对象的问题,对于自定义类型而言,auto_ptr的析构函数仅能够析构一个对象,不能够处理一组对象的情况,这些都是尚未解决的问题。

auto_ptr指针当使用赋值语句将ptr1赋值给ptr2时,程序并未报错,但实际上存在隐患。问题1:auto_ptr并不共享管理权,当使用赋值语句将指针赋值后,ptr1将失去对内存的管理权。问题2:程序结束时,内存释放时会被释放两次,引发程序崩溃。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值