我现在在我的代码中有一个生成std::vector<SomeHeavyComplexType>
的函数(在下面的代码中只是一个int):
inline std::vector<int> generateComplexConf() {
return {1,2,3,4,5};
}
struct MyComplexStruct {
const std::vector<int> my_conf;
MyComplexStruct() : my_conf(generateComplexConf()) {}
};
这很好,但AFAIK初始化列表是const - 所以上面的代码将在generateComplexConf
中生成一个std :: vector,然后将其复制到MyComplexStruct的元素中。
更好的选择是:
inline std::vector<int> generateComplexConf() {
std::vector<int> ret;
ret.emplace_back(1);
ret.emplace_back(2);
...
return ret;
}
struct MyComplexStruct {
const std::vector<int> my_conf;
MyComplexStruct() : my_conf(std::move(generateComplexConf())) {}
};
现在std :: vector&lt;&gt;刚刚感动。
我的问题是:
上面的2段代码是否有更好的替代方案 - 即有些东西可以生成与MyComplexStruct() : my_conf{1,2,3,4}
完全相同但允许配置对象({1,2,3,4,5}
)的代码与MyComplexStruct
如果没有,在我使用std::move
的代码中,这迫使我多次使用emplace_back(在我的实际代码中数百次)。您是否知道具有更好语法的内容 - 即具有非常量的初始化列表?
编辑:
在评论之后,我应该添加一些精确度。为了澄清我的问题,想象一下std::vector<int>
而不是std::vector<Test>
,其中Test不可复制,不可移动,不可分配,例如:
struct Test {
int a;
Test(int x) : a(x) {}
Test() : a(1) {}
Test(Test&&) = delete;
Test(const Test&) = delete;
Test& operator=(Test&&) = delete;
Test& operator=(const Test&) = delete;
};
inline std::vector<Test> generateConf() {
return {Test{1},Test{2}};
}
inline std::vector<Test> generateConfMove() {
std::vector<Test> r;
r.emplace_back(1);
r.emplace_back(2);
return r;
}
struct MyComplexStruct {
const std::vector<int> my_conf;
MyComplexStruct() : my_conf(generateConf()) {}
};
虽然generateConf
会尝试使用Test的复制构造函数,generateConfMove
会尝试使用Test的移动构造函数(因为有人在评论中相应地更正了我,data
初始化列表的列表是const)。
如果我重新提出我的两个问题:
在Test
不可移动且不可复制的一般情况下,无论如何都要将代码配置在与构造函数不同的位置
如果Test
只是非可复制的,那么emplace_back工作正常。但在这种情况下,是否还有其他更符合语法的&#39;这样做的方法?
答案 0 :(得分:0)
你的第一次剪裁非常精细 - 无法改进 - 事情从那里开始走下坡路。编译器足够聪明,知道当一个函数按值返回时,该值可以在调用者分配时直接删除和构造,或者 - 失败(它不能保证在C ++之前省略) 17) - 必要时离开。
但是允许将代码配置对象({1,2,3,4,5})放在与MyComplexStruct定义不同的地方?
没有比你已经做过的更好的了。如果您未在初始化列表中进行分配,则向量数据成员my_conf
将默认构建,然后您必须在以后将值放入其中 - 效率较低。< / p>