最开始在写一个 命令模块, 涉及到 简单命令 和 复合命令。
所有的命令 是通过字符串组装的。
命令的调用是通过注册机制 实现绑定的。
具体的功能封装在对应的 功能类里面。
由于复合命令的存在,会导致一条命令 执行多个处理。
所以希望在 注册的时候,能够直接将多个对象直接保存到一个容器内。
这就会涉及到 不定长参数 保存的 过程。
在这里我才用了变长参数模版。
我先定义一个通用的 key-value 的 变长模版, 用于构造一个容器对象。
指定 当输入类型 为 key-value:string-string时,对应的处理方法。
当然也可以指定其他类型的参数和对应的处理函数。
template<typename... Params>
MapSet Register(string key, string value, Params... params) {
auto map_set = Register(params...);
map_set.add(key, value);
return map_set;
}
设定模版扩展的终止条件
template<typename... Params>
MapSet Register() {
return MapSet("null");
}
这样 就能把想要的参数保存在对应的容器中。
在使用变长模版函数的过程中,我在想 每个函数都构造一个对象, 会导致接收的时候都调用拷贝构造。
所以我在定义容器的时候,定义了拷贝构造,和右值引用构造,方便查看调用过程。
最开始,我没有实现 右值引用,只是实现拷贝构造
MapSet(const MapSet& map_set) {
dictory_ = map_set.dictory_;
index = AddRef();
cout << "construct from : const Copy, index :" << index << endl;
}
MapSet(MapSet& map_set) {
dictory_ = map_set.dictory_;
index = AddRef();
cout << "construct from : Copy, index :" << index << endl;
}
结果如图:
后来加入 右值引用
MapSet(MapSet&& map_set) {
dictory_.swap(map_set.dictory_);
index = AddRef();
cout << "construct from : Swap, index :" << index << endl;
}
}
结果如图:
发现 没有触发右值引用
再次修改代码
template<typename... Params>
MapSet Register(string key, string value, Params... params) {
auto map_set = Register(params...);
map_set.add(key, value);
return std::move(map_set);
}
结果如图:
现在已经触发了 右值引用, 其中8次构造 发生了 7次交换。
后来朋友告诉我 c++ 有返回值优化,于是 去掉std::move,把debug 编译 换成release 编译 再次尝试。
template<typename... Params>
MapSet Register(string key, string value, Params... params) {
auto map_set = Register(params...);
map_set.add(key, value);
return map_set;
}
结果如图:
这里产生2次构造,其中发生一次交换。
这里不同的编译器优化效果可能不一样,下面使用 blade 编译的
完整代码:
#include <iostream>
#include <string>
#include <map>
using namespace std;
int AddRef() {
static int ref = 0;
return ref++;
}
class MapSet{
public:
MapSet(string info = "") {
index = AddRef();
cout << "construct from : " << info << ", index :" << index << endl;
}
MapSet(const MapSet& map_set) {
dictory_ = map_set.dictory_;
index = AddRef();
cout << "construct from : const Copy, index :" << index << endl;
}
MapSet(MapSet& map_set) {
dictory_ = map_set.dictory_;
index = AddRef();
cout << "construct from : Copy, index :" << index << endl;
}
MapSet(MapSet&& map_set) {
dictory_.swap(map_set.dictory_);
index = AddRef();
cout << "construct from : Swap, index :" << index << endl;
}
void add(string key, string value) {
dictory_.emplace(std::make_pair(key, value));
}
void print() {
cout << "output" << endl;
for (auto it : dictory_) {
cout << it.first << " : " << it.second << endl;
}
}
private:
map<string, string> dictory_;
int index;
};
template<typename... Params>
MapSet Register() {
return MapSet("null");
}
template<typename... Params>
MapSet Register(string key, string value, Params... params) {
auto map_set = Register(params...);
map_set.add(key, value);
return map_set;
}
int main() {
Register("a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "f", "f").print();
getchar();
return 0;
}