你能初始化unique_ptrs "static const vectors"吗?(C++17 与 GCC 7.3)



我正在尝试创建一个默认对象(规则)的static const列表,这些对象(规则)很大,可以经常复制,因此我想将它们存储在unique_ptr<>vector中。我注意到类似的问题已经出现了几次,但我不清楚这是否真的可行(我倾向于不可行)。即

  1. 不能将initializer_listunique_ptr一起使用,因为对成员的访问非常大,会导致复制操作。
  2. 不能通过引用传入临时,从而导致复制操作。

因此,两者:

static const std::vector<std::unique_ptr<std::string>> kStrings = {
std::unique_ptr<std::string>(new std::string("String 1")),
std::unique_ptr<std::string>(new std::string("String 1"))
};

static const std::vector<std::unique_ptr<std::string>> kStrings(
std::unique_ptr<std::string>(new std::string("String 1")),
std::unique_ptr<std::string>(new std::string("String 1"))
);

是不可行的。

我是不是误会了?有没有另一种方法可以初始化这样的向量,或者这是重新思考设计的情况?我能想到的最简单的替代方法是创建对象static const,然后将其引用为原始指针。例如:

static const std::string kString1 = "String 1";
static const std::string kString2 = "String 2";
static const std::vector<const std::string*> kStrings = {&kString1, &kString2};

感觉很讨厌,但代码接口保持相对不变,并且由于它不离开类的范围,因此对用户也是透明的。

任何想法,更正或更好的替代方案将不胜感激。

编辑- 关于这个问题,我已经测试了解决方案,它也可以工作。我对解决方案的问题是,它使initializer_list能够以它们不是设计用于使用的方式使用,我不知道这将产生什么意想不到的后果,如果有的话。

我是不是误会了?有没有另一种方法可以初始化这样的向量

有一个,调用一个返回非常量向量的函数以用作初始值设定项。它甚至不必命名。它可能是一个立即调用的 lambda。

static const std::vector<std::unique_ptr<std::string>> kStrings = [] {
std::vector<std::unique_ptr<std::string>> ret;
// populate ret
return ret;
}(); // <-- Invoke the lambda immediately after defining it. 

现在,您可以拥有复杂的初始化逻辑,并kStrings视为常量。此外,编译器很可能会完全内联lambda,因此甚至不会有函数调用的开销。它真的是吃你的蛋糕和吃它。

尽管人们不得不想知道为什么要使用指向字符串(值类型)的唯一指针向量。矢量已经拥有其内容。因此,您可以削减中间人,这也将简化初始化。

最新更新