具有初始化列表的"内联"对象的静态声明

Jab*_*cky 15 c++ vector c++11

抱歉尴尬的标题,但我找不到更好的标题.

考虑这个示例代码(除了说明问题之外没有任何目的):

#include <vector>

void FooBar(int);

void func1()
{
    static std::vector<int> vec {1, 2, 3, 4};

    for (auto & v : vec)
      FooBar(v);
}

void func2()
{
    for (auto & v : std::vector<int> {1, 2, 3, 4})
      FooBar(v);
}
Run Code Online (Sandbox Code Playgroud)

可以在此处找到对此的反汇编

func1静态vec向量中应该在启动时一劳永逸地构造.实际上上面提到的godbolt上的反汇编表明静态的初始化vec只在第一次调用时完成,func1而不是在启动时完成,但这不是重点.

现在考虑func2:这里向量直接在for语句中声明为"内联"(不确定这是如何实际调用的),但当然每次func2调用时都会构造该向量.

是否有静态声明向量的方式里面for的语句,像for (auto & v : static std::vector<int> { 1, 2, 3, 4})这是不幸的是没有合法的C++.

Sto*_*ica 12

这实际上对你没有帮助.但是你可以在C++ 2a中做些什么.但是,它基于C++ 14和C++ 17中已有的东西.

C++ 2a添加了一个init-statement基于循环的范围.这是新的一点,旧的一点是,它与init-statement今天定义的相同.定义如下([stmt.stmt]):

init-statement:
    expression-statement
    simple-declaration
Run Code Online (Sandbox Code Playgroud)

我想要的是a simple-declaration可能包含一个static限定符.是的,它会做你所期望的.所以在C++ 2a中你可以写:

for (static std::vector<int> vec {1, 2, 3, 4}; int v : vec) {
   // Do things.
}
Run Code Online (Sandbox Code Playgroud)

如果你想今天测试它的编译器支持,这里是一个C++ 17 kludge:

if (static std::vector<int> vec {1, 2, 3, 4}; true) {
    // init-statement in if was added in C++17
  for(int v : vec)
    FooBar(v);
}
Run Code Online (Sandbox Code Playgroud)

它的拆卸.

  • 嗯,我不知道这里可以包含 `static`(从来没有任何理由尝试过)。`if` 版本比打开一个新的块作用域有什么好处吗? (2认同)

wal*_*lly 8

使用lambda的另一个选项(来自主要问题的评论):

void func()
{
    for(auto & v : ([]() -> std::vector<int>& { static std::vector<int> vec{1, 2, 3, 4}; return vec; })())
        FooBar(v);
}
Run Code Online (Sandbox Code Playgroud)

  • @Scheff - 通过函数调用,它调用lambda并获取迭代的向量.没有调用,它会尝试迭代lambda对象本身. (4认同)