【面试八股】面试题记录

1.文章目的

为了记录一些网上看到或自己遇到的面试理论问题,比如一些自己觉得值得记录或不熟练的问题,在有需要的时候会来更新

2.注意

这篇文内容应该会比较随机,想起来想看点什么就写点什么,所以整体可能会很不成体系,目前预计的话可能会以C++和ML的相关内容为主

3.内容

(1).智能指针相关

智能指针的作用:帮助管理动态分配的内存,自动释放防止内存泄漏
有几个类型的智能指针:auto_ptr, unique_ptr, shared_ptr, weak_ptr

(a).auto_ptr

C++98中定义的智能指针模板,通过new间接或直接的降低至赋给对象,当对象过期时,自动释放内存
auto_ptr的声明:auto_ptr包含在memory头文件中

/*auto_ptr的声明*/
#include<memory>

//auto_ptr<typename> ptrname(new typename());
auto_ptr<string> stringPtr(new string("the auto ptr"));

auto_ptr的使用:在使用auto_ptr时候,当指针对象的生命周期结束,不需要delete这个指针,指针会自动调用析构函数用来释放内存空间

int main(){
	auto_ptr<string> stringPtr(new string("autoptr"));
	std::cout<<*stringPtr<<std::endl;
	return 0;
}

也就是在上面的写法中,即是没有delete stringPtr,也不需要担心内存泄露的问题。

auto_ptr常用的几个函数:get(),release(),reset()

//get():获取智能指针托管的地址
auto_ptr<string> strPtr(new string("autoptr"));
string *sptr = strPtr.get();
std::cout<<*sptr<<std::endl;
//release():取消对智能指针的内存托管
auto_ptr<string> strPtr(new string("autoptr"));
string *sptr = strPtr.get();//取消智能指针的内存托管
delete sptr;
//reset():重置智能指针的托管地址,如果地址不一样,原本的地址会被析构掉
auto_ptr<string> strPtr(new string("autoptr"));
strPtr.rest(new string("restptr"));
//这里的autoptr字符串已经被析构掉了

关于auto_ptr的问题:
auto_ptr在复制或者赋值后都会改变资源的所有权,如:当将auto_ptr的p2赋值给p1后,此时p1会将自己原本托管的内存释放掉,然后接受p2所托管的内存,而此时p2也会放弃自己所托管的内存,因此将会出现p2的托管内存为空的情况,当在STL中,会存在大量的赋值,复制操作,因此,auto_ptr无法适应这时的使用需求

(b) unique_ptr

在C++11之后,为了解决auto_ptr的排他所有权问题,提出了unique_ptr。
关于unique_ptr有以下几种特性
1.排他性:两个unique_ptr指针不能指向同一个资源
2.无法使用左值赋值构造,但允许临时右值赋值和构造
3.保存只想某个对象的指针,当他本身离开作用域时候会自动释放他所指向的对象
4.在容器中保存指针是安全的

关于不允许左值赋值和构造

unique_ptr<string> p1(new string("uniqueptr p1"));
unique_ptr<string> p2(new string("uniqueptr p2"));

p2 = p1;//错误,因为p1是左值
unique_ptr<string> p3(p2);//错误,不允许使用左值来进行构造

//如果想要使用左值来进行构造,需要使用move函数来将左值转换为右值
unique_ptr<string> p4(std::move(p2));
//或者
p2 = std::move(p1);

关于STL容器中使用unique_ptr

//不允许直接赋值,需要使用move修饰
vector<unique_ptr<string>> vec;
unique_ptr<string> p1(new string("uniqueptr p1"));
unique_ptr<string> p2(new string("uniqueptr p2"));

vec.push_back(p1);//错误,此时p1为左值
vec.push_back(std::move(p1));//正确,需要提示写者这里将p1转为右值
vec[0] = vec[1];//同样错误,此时的vec[1]为一个unique_ptr,为左值,不能进行赋值
vec[0] = std::move(vec[1]);//正确

(c)shared_ptr

由于auto_ptr和unique_ptr的排他性,但实际任务中还需要一系列的共享指针,因此C++使用shared_ptr来解决这个问题

shared_ptr可以多个指针指向同一块内存,并且shared_ptr有一个引用计数器,当每多一个复制或者拷贝时(也就是每多一个shared_ptr指向目标内存时),引用计数器+1,反之则引用计数器-1,当引用计数器为0时,自动释放内存。

关于引用计数器:使用use_count()函数来获得当前托管指针的引用计数

shared_ptr<string> sp1(new string("sharedptr sp1"));
shared_ptr<string> sp2(sp1);

std::cout<<sp2.use_count()<<std::endl;//2
std::cout<<sp1.use_count()<<std::endl;//2

关于shared_ptr的构造

//shared_ptr可以指向类型为T的对象
shared_ptr<T> sp1;
T *t = new T(1);
sp1.reset(t);
//另一种构造方式,shared_ptr可以直接在构造中调用类型T的对象进行构造
shared_ptr<T> sp2(new T(2));
shared_ptr<T> sp3(sp2);
//在C++17以后,shared_ptr支持指向类型为T[]的数组
shared_ptr<T[]> sp4;
shared_ptr<T[]> sp5(new T[5]{3,4,5,6,7});

shared_ptr的问题:
在作为被管控的对象的成员时,会因为循环引用造成无法释放资源
如下所示

#include <iostream>
#include <string>
#include <memory>

using namespace std;

class Girl;

class Boy {
public:
	Boy() {
		cout << "Boy 构造函数" << endl;
	}

	~Boy() {
		cout << "~Boy 析构函数" << endl;
	}

	void setGirlFriend(shared_ptr<Girl> _girlFriend) {
		this->girlFriend = _girlFriend;
	}

private:
	shared_ptr<Girl> girlFriend;
};

class Girl {
public:
	Girl() {
		cout << "Girl 构造函数" << endl;
	}

	~Girl() {
		cout << "~Girl 析构函数" << endl;
	}

	void setBoyFriend(shared_ptr<Boy> _boyFriend) {
		this->boyFriend = _boyFriend;
	}

private:
	shared_ptr<Boy> boyFriend;
};


void useTrap() {
	shared_ptr<Boy> spBoy(new Boy());
	shared_ptr<Girl> spGirl(new Girl());

	// 陷阱用法
	spBoy->setGirlFriend(spGirl);
	spGirl->setBoyFriend(spBoy);
	// 此时boy和girl的引用计数都是2
}


int main(void) {
	useTrap();

	system("pause");
	return 0;
}

关于智能指针的内容参考
https://blog.csdn.net/cpp_learner/article/details/118912592

(2)C++中的string::npos问题

1.string::npos

关于string::npos的定义,npos是一个公有的静态的常量类型的成员变量

static const size_type	npos = static_cast<size_type>(-1);

在string类中,表示until the end of string,也就是直到字符串尾部的一个常量计数值

2.string::npos的优势

npos是一个特殊的常量值,因此可以让stl的遍历和查找效率更高,同时防止一些错误的越界写法

3.string::npos的写法

bool findTarget(string s1, string s2){
	auto found = s1.find(s2);
	//检查位置是否等于npos,如果等于说明不存在target串
	if(found != string::npos){
		return false;
	}
	return true;
}

因此,npos一般用于说明find()操作时没有查找到的状态

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值