C++有个令人头痛的点是会出现一些极其复杂的变量声明,比如:
string(const** f(int, void (*const p)(int)))(char[]);
2025/9/1大约 2 分钟
C++有个令人头痛的点是会出现一些极其复杂的变量声明,比如:
string(const** f(int, void (*const p)(int)))(char[]);
提示
在 C# 中,装箱(Boxing)和拆箱(Unboxing)是值类型与引用类型之间转换的重要概念,它们涉及到内存分配和性能考虑。
装箱是将值类型转换为引用类型的过程。当值类型需要被当作对象处理时(例如存储在非泛型集合中),系统会在堆(Heap)上分配内存,将值类型的数据复制到堆上,并返回该对象的引用。
int value = 42; // 值类型,存储在栈上
object boxed = value; // 装箱:值被复制到堆上,boxed引用该对象
众所周知,根据创建时机单例模式分为懒汉式和饿汉式,根据线程是否安全分为线程安全和线程不安全。
最近看Cherno的一个讲解视频,对于单例模式有了一个新的认识。Cherno认为,给单例提供一个随时随地的访问接口不利于游戏引擎这种底层框架的设计,会打乱程序的树状架构。
对于下面这个单例实现方式,根据静态对象的构造时机以及C++11后局部静态变量在第一次被访问时初始化是线程安全的特性,很容易得到这是饿汉式线程安全的一种实现。但这种方式不能直观地显式创建和销毁单例对象,尤其是当应用程序有多个单例,而且单例间存在依赖关系,需要特定的创建和销毁顺序。
最近发现C++里面可以通过实现lock、unlock两个方法实现自定义锁,因此去看了下MSVC中std::lock_guard的C++11实现。lock_guard通过在构造函数中调用lock函数上锁、在unlock函数解锁。
_EXPORT_STD template <class _Mutex>
class _NODISCARD_LOCK lock_guard { // class with destructor that unlocks a mutex
public:
using mutex_type = _Mutex;
explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock
_MyMutex.lock();
}
lock_guard(_Mutex& _Mtx, adopt_lock_t) noexcept // strengthened
: _MyMutex(_Mtx) {} // construct but don't lock
~lock_guard() noexcept {
_MyMutex.unlock();
}
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
_Mutex& _MyMutex;
};