C++的右值引用

右值引用主要用于移动语义(Move semantics)和完美转发(Perfect forwarding) Move semantics Move semantics能转移一个对象到另一个对象上,避免不必要的内存拷贝,被拷贝对象不能在其它地方被引用。要实现Move semantics只要给类定义移动构造函数和可选的移动赋值操作: class Memory { public: Memory(Memory&& other) noexcept { _data = other._data; _length = other._length; other._data = nullptr; other._length = 0; } Memory& operator=(Memory&& other) noexcept { if (this != &other) { delete[] _data; _data = other._data; _length = other._length; other._data = nullptr; other._length = 0; } return *this; } private: void *_data{nullptr}; int _length{0}; } Perfect forwarding Perfect forwarding主要为了减少重载函数,主要是泛型函数用引用类型作为参数。 struct W { W(int&, int&) {} }; struct Z { Z(const int&, const int&) {} }; template <typename T, typename A1, typename A2> T* factory(A1& a1, A2& a2) { return new T(a1, a2); } int a = 4, b = 5; W* pw = factory<W>(a, b); // OK Z* pz = factory<Z>(2, 2); // Valid cause 2 is right value 把上面的泛型函数参数改成右值引用就能解决这个问题: template <typename T, typename A1, typename A2> T* factory(A1&& a1, A2&& a2) { return new T(std::forward<A1>(a1), std::forward<A2>(a2)); } Z* pz = factory<Z>(2, 2); // OK References: https://learn.microsoft.com/en-us/cpp/cpp/rvalue-reference-declarator-amp-amp?view=msvc-170

January 16, 2022 · 1 min · Jee

C++跨平台项目开发

简介:记录开发一个跨平台C++项目的历程 1. 背景 我司服务端项目大部分使用一个简单的模式:C++做底层负责网络/内存/多线程/日志等,内嵌一个Lua虚拟机,业务逻辑都用Lua写。这个模式既能提供高性能,又能让业务逻辑开发简单,安全。多年来运作良好。 过去几年,服务端的开发和运行环境均在Linux下。今年要开一个新项目,我心血来潮想要在Windows下开发,当然线上还是部署在Linux中。所以就需要让这个项目同时支持Linux和Windows。业务层面好说,因为用Lua开发,本身100%跨平台。所以只需要让C++代码能跨平台编译运行即可。 2. C++跨平台编译运行 我们的C++项目主要依赖STL/Lua/Socket库。 STL本身就是跨平台的,只要有C++编译器即可。线程库用的c++11的std::thread。Easy! Lua源代码是用标准C89写,基本零依赖,几乎所有平台都可以编译,但我懒的自己编译了,所以直接用社区提供的LuaBinaries。 Socket库我们是自己开发的,所以简单封装了一个Socket类,底层根据不同平台调用不同的API,对外提供统一的抽象接口。 遇到的第一个问题是:如何"一键"在Win/Linux下编译 Linux平台下,我们一直用Makefile,所以轻车熟路的写了一个,搞定Linux下编译。 Windows平台下,就没那么简单了,绕了点弯路。由于我本身用了多年的cygwin,所以直接用cygwin下的gcc编译,还能直接用我为Linux平台写的Makefile。这一步也很简单,但问题出在Lua的C模块上,我们用了一些开源的Lua C模块,例如lua-cjson,这个东西虽然也可以在cygwin下编译,但运行时Lua虚拟机总是不能正确加载,折腾了好久最终放弃。因为考虑到以后可能还会用到其他开源的项目,而且其他项目成员也不一定都喜欢装一个cygwin,所以我还是决定弄成Windows原生的exe和dll。 安装了一个VS2019(这东西真大,十几个G),所有C++代码丢进去,配置下链接上面提到的LuaBinaries,运行完美。那开源的项目如何编译成原生dll呢?由于开源项目大多提供了Makefile或CMake的编译脚本,很少直接提供VS工程的,所以我决定用mingw。下面以编译lua-cjson为例记录下过程。 安装MingW,并将MingW的bin目录加入Path中 下载lua-cjson-2.1.0(https://www.kyne.com.au/\~mark/software/download/lua-cjson-2.1.0.tar.gz) 修改lua-cjson的Makefile,放开## Windows (MinGW)下面的注释 ## Windows (MinGW) CC = gcc # 增加此行 TARGET = cjson.dll PREFIX = c:/LuaBinaries # 改成你的LuaBinaries目录 CJSON_CFLAGS = -DDISABLE_INVALID_NUMBERS CJSON_LDFLAGS = -shared -L$(PREFIX) -llua53 # 这里根据你的Lua版本配置 然后打开CMD,cd到lua-cjson-2.1.0目录,运行: mingw32-make 踩到过的坑:链接lua dll时gcc报错"lua53.dll 无法识别的格式"。卡了半天才发现原来mingw的32位和64位是两个独立的项目。我用google搜mingw的官网,找到了(https://sourceforge.net/projects/mingw/),这个是32位的。而我下载的LuaBinaries是64位,自然链接不到。64位的mingw是这个(https://sourceforge.net/projects/mingw-w64/),注意根据你的平台选择正确的版本!

May 22, 2021 · 1 min · Jee