Ask*_*ker 1 c++ intellisense initializer-list constexpr visual-studio-code
这是问题所在:
int main()
{
constexpr std::initializer_list<int> my_ints {1, 2, 3};
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用 g++ (x86_64-posix-seh-rev0, version 8.1.0) 编译上述内容。但是 VS Code 引发了以下警告:
“表达式必须有一个常量值——生命周期有限的临时引用或指针”
当我删除说明constexpr符时,也就是当我将代码修改为
int main()
{
std::initializer_list<int> my_ints {1, 2, 3};
}
Run Code Online (Sandbox Code Playgroud)
错误消失了,所以声明 a 似乎有问题constexpr initializer_list。
然而根据这个参考(https://en.cppreference.com/w/cpp/utility/initializer_list/initializer_list),声明一个constexpr initializer_list.
有人可以更深入地了解其工作原理constexpr并initializer_list解释为什么会发生这种情况吗?
在cppreference有一个关于这个问题原因的线索:
std::initializer_list 类型的对象是一个轻量级代理对象,它提供对 const T 类型的对象数组的访问。
和:
初始化列表可以实现为一对指针或指针和长度。
换句话说,当您在本地范围内执行此操作时:
std::initializer_list<int> my_ints {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
编译器必须{1, 2, 3}在堆栈上分配(和初始化),所以它不能是constexpr.
幸运的是,有一个简单的解决方法。做就是了:
static constexpr std::initializer_list<int> my_ints {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
现在底层数组是在编译时分配的,因此可以是constexpr.
生成的代码的差异可以在Godbolt看到。
编辑: OP 询问(实际上)可以基于堆栈的变量constexpr吗?好吧,答案是肯定的,如果该对象的所有成员都可以在编译时进行评估。
所以,回到原来的例子,当你写:
std::initializer_list<int> my_ints {1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
astd::initializer_list通常由一个指向底层数组的指针和一个长度组成,因此,在这里,编译器必须在运行时将1,2和3推入堆栈,然后将指向该“数组”的指针和长度放入my_ints,因此my_ints不能constexpr因为所述数组的地址在编译时未知。
OTOH,类似于:
constexpr int i = 42;
Run Code Online (Sandbox Code Playgroud)
很好,因为 42 在编译时(显然)是已知的,这就是编译器关心的全部。
有趣的是:
constexpr char s [] = "abcde";
Run Code Online (Sandbox Code Playgroud)
也有效。如果您查看生成的代码,编译器会在静态存储中分配“abcde”,然后s在运行时将其复制到。为什么它不做类似的事情std::initializer_list有点神秘(至少对我来说)。
最后,为什么声明可以my_ints static解决问题?那么,现在的编译器可以分配并初始化1,2,3在编译时,该“阵列”现在是在其在编译时已知这样的地址my_ints可constexpr。
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |