1. 如何实现一个智能指针?智能指针是否线程安全?
shared_ptr是线程安全的吗? shared_ptr的引用次数加减操作内部自动加锁解锁,是线程安全的。但是指向对象的指针不是线程安全的 一、使用智能指针访问资源不是线程安全的,需要手动加锁解锁。 二、智能指针的拷贝也不是线程安全的 智能指针的赋值拷贝,首先拷贝指向对象的指针,再使引用次数加减操作,虽然引用次数加减是原子操作, 但是指针拷贝和引用次数两步操作 并不是原子操作,线程不安全,需要手动加锁解锁
shared_ptr会有循环引用的问题 A类有指向B对象的指针,B类有指向A对象的指针,这时候就需要shared_ptr和weak_ptr配合使用。 weak_ptr没有count计数,直接释放,weak_ptr相当于普通指针。
shared_ptr并不是指针,是一个类对象,shared_ptr内部有指针成员变量,实现了->和*运算符重载,->返回一个指针。所以不能直接把指针赋值给shared_ptr。
2. 可调用对象包装器和绑定器是什么?
可调用对象包装器std::function:可调用对象包装器是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。使用对象包装器std::function可以非常方便的将仿函数转换为一个函数指针,通过进行函数指针的传递,在其他函数的合适的位置就可以调用这个包装好的仿函数了。
绑定器std::bind:用来将可调用对象与其参数一起进行绑定。绑定后的结果可以使用std::function进行保存,并延迟调用到任何我们需要的时候。通俗来讲,它主要有两大作用:
- 将可调用对象与其参数一起绑定成一个仿函数。
- 将多元(参数个数为n,n>1)可调用对象转换为一元或者(n-1)元可调用对象,即只绑定部分参数。
std::bind绑定器返回的是一个仿函数类型,得到的返回值可以直接赋值给一个std::function,在使用的时候我们并不需要关心绑定器的返回值类型,使用auto进行自动类型推导就可以了。
std::bind可以将函数及其参数进行绑定,那么参数的位置与传入的位置相关,因此有了占位符的概念,placeholders::1 是一个占位符,当函数传入第一个参数的时候,就会把其进行替换,同理std::palceholders:: 2是第二个占位符。
3. 常见类型转换方式static_cast、dynamic_cast、reinterpret_cast、const_cast各自特点和区别?
4. C++函数签名(Function Signature)与调用特征标(Calling Convention)的区别?
函数签名:是函数的名称以及它接受的参数列表,包括参数的类型、数量和顺序。函数签名用于在编译时确定函数的标识,是函数重载(Overloading)和函数调用的基础。在C++中,函数签名还可能包括const修饰符、引用或指针修饰符等,这些都会影响函数的匹配和调用。
调用特征标:定义了函数调用时的底层细节,即函数调用时的参数传递方式(通过寄存器、栈或两者的组合),函数返回值传递的约定,调用者(caller)还是被调用者(callee)负责释放参数列表所占用的内存空间(栈上的清理)。调用特征标定义了函数如何接收参数、如何返回值以及在调用过程中栈上如何管理这些参数和返回值。
同一个函数可以有不同的调用特征标实现,例如,一个函数可以用__cdecl(C调用特征标)或__stdcall(stdcall调用特征标)来实现。调用特征标通常由编译器或平台指定,开发者也可以在必要时明确指定。