作为免责声明,我在询问之前已对此进行过研究.我发现了一个类似的问题,但答案有点"稻草人",并没有真正回答我个人的问题.我也提到了我方便的cppreference页面,但这并没有提供对事物的非常"愚蠢"的解释.
基本上我还在继续constexpr,但目前我的理解是它需要在编译时评估表达式.由于它们可能仅在编译时存在,因此它们在运行时不会真正具有内存地址.因此,当我看到人们使用时static constexpr(例如在类中)static会让我感到困惑...... 因为这只对运行时上下文有用,所以在这里会是多余的.
我在" constexpr除了编译时表达式之外不允许任何东西"声明中看到了矛盾(特别是在SO).但是,Bjarne Stroustrup的页面中的一篇文章在各种示例中解释了实际上constexpr 确实需要在编译时对表达式进行评估.如果不是,则应生成编译器错误.
我之前的段落似乎有点偏离主题,但它是理解为什么static可以或应该使用的必要基线constexpr.不幸的是,该基线有很多矛盾的信息浮出水面.
任何人都可以帮助我将所有这些信息整合到纯粹的事实中,并提供有意义的示例和概念吗?基本上在了解constexpr真实行为的基础上,您为什么要使用static它?通过什么范围/场景确实static constexpr有意义,如果它们可以一起使用?
在C++中声明和定义全局常量的最佳方法是什么?我最感兴趣的是C++ 11标准,因为它在这方面做了很多修复.
[编辑(澄清)]:在这个问题中,"全局常量"表示在编译时在任何范围内已知的常量变量或函数.必须可以从多个翻译单元访问全局常量.它不一定是constexpr风格不变-可以是这样const std::map<int, std::string> m = { { 1, "U" }, { 5, "V" } };或const std::map<int, std::string> * mAddr() { return & m; }.在这个问题中,我没有触及优选的好的范围或常数名称.让我们把这些问题留给另一个问题.[END_EDIT]
我想知道所有不同情况的答案,所以让我们假设这T是以下之一:
typedef int T; // 1
typedef long double T; // 2
typedef std::array<char, 1> T; // 3
typedef std::array<long, 1000> T; // 4
typedef std::string T; // 5
typedef QString T; // 6
class T {
// unspecified amount of code
}; // 7
// …Run Code Online (Sandbox Code Playgroud) 我对一个constexpr概念感到困惑,因为我读过的constexpr是在编译时进行评估,因此它对于性能优化与正常情况相比非常有用const.
constexpr int i = 0;
constexpr int& ri = i;
Run Code Online (Sandbox Code Playgroud)
上面的代码返回一个错误"从'const int'类型的表达式中无效初始化类型'int&'的引用",为什么?
此外,下一个代码有一个错误:
constexpr int i = 0;
constexpr int* ri = &i;
Run Code Online (Sandbox Code Playgroud)
如果我替换了constexpr关键字const,以上所有都正常工作.
此 C++ 代码无法编译:
#include <iostream>
int main()
{
constexpr int kInt = 123;
struct LocalClass {
void func(){
const int b = std::max(kInt, 12);
// ^~~~
// error: use of local variable with automatic storage from containing function
std::cout << b;
}
};
LocalClass a;
a.func();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但这有效:
#include <iostream>
#include <vector>
int main()
{
constexpr int kInt = 123;
struct LocalClass {
void func(){
const int b = std::max((int)kInt, 12); // added an extra conversion "(int)"
std::cout …Run Code Online (Sandbox Code Playgroud) 为什么下面的工作原理gcc却没有clang,(现场观看):
constexpr int giveMeValue() { return 42; }
struct TryMe {
static constexpr int arr[1] = {
giveMeValue()
};
};
int main() {
int val = TryMe::arr[0];
return val;
}
Run Code Online (Sandbox Code Playgroud)
我得到一个未解决的外部符号与clang.
是TryMe::arr[0]一个对象?如果是的话,它是否经常使用?
我知道const和constexpr之间的区别.一个是编译时常量,另一个是编译时或运行时常量.
但是,对于字符/字符串数组,我很困惑为什么编译器抱怨一个用于另一个.
例如,我有:
constexpr char* A[2] = {"....", "....."};
const constexpr char* B[2] = {"....", "....."};
Run Code Online (Sandbox Code Playgroud)
声明"A"我得到:
ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Run Code Online (Sandbox Code Playgroud)
但声明"B"我没有得到任何警告.
为什么额外的const限定符会消除警告?他们两个都不是"const char*"吗?我问,因为两者都被声明,默认情况下constexpr应该使它成为一个const char*?
我希望A没问题:S
我一直在读一本关于C++ 14/11的书.我刚刚读完了关于该constexpr关键字的章节.我知道它用于什么,但我应该多久使用一次constexpr?即使在我知道永远不会用于创建contstexpr对象的类的代码中,我是否应该使用它?(以防万一,因为它不会让我付出任何代价,对吧?)
尽管阅读了一些 StackOverflow 帖子(this和this)和 cppreference 页面,但我无法弄清楚非静态局部变量与非静态局部变量 相比有何constexpr好处。 static constexpr
我能看到的唯一区别是每个调用都有自己的实例,但由于它是一个constexpr我在这里看不到实际优势(因为,如果我理解正确,这会导致每个实例都是相同且不可变的,使得多个实例只是多余的)。
或者,从另一个角度争论:由于非静态constexpr局部变量在(每次)函数调用时初始化,因此简单局部变量没有任何优势const,尽管它可以用于编译时评估。但是,当编译时评估需要它们时,没有必要将它们设置为非静态的。
所以我的问题是:我的论点有什么缺陷,在什么情况下非静态constexpr局部变量是合理的并且可能是最佳选择?
我有一段将整数映射到整数的生成代码,其核心是一个简单的表。在 C++17 之前,它曾经是这样的:
int convert (int v)
{
static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
if (0 <= v && v < sizeof table / sizeof table[0])
return table[v];
else
return -1;
}
Run Code Online (Sandbox Code Playgroud)
使用 C++17,我想使用 constexpr。我预计增加constexpr的函数签名就足够了,但我要删除的static表,这让我实施显然没有很好的理由更加复杂。没有太多提及,table在非constexpr情况下很可能会在堆栈上,所以我想我应该更换 static的constexpr。
G++ 8 报告:
/tmp/foo.cc: In function 'constexpr int convert(int)':
/tmp/foo.cc:14:26: error: 'table' declared 'static' in 'constexpr' function
static const int table[] = { …Run Code Online (Sandbox Code Playgroud) 这个问题(和代码)的灵感来自 Jason Turner 的《C++ Weekly》一集:停止使用constexpr(并使用此代替!)
假设下面的代码(编译器资源管理器)
我的理解是,在声明函数局部变量时,static constexpr我保证该变量仅初始化一次(静态),并且如果编译器无法证明单线程访问(由于它是 constexpr),通常不需要任何线程安全开销。
但是c++标准能保证这一点吗?标准中是否有任何地方可以确保我该行static constexpr auto arr = getArr();永远不会导致编译器添加互斥体或其他类型的线程保护?
Jason Turner 的剧集或这个 stackoverflow 问题都没有提到局部静态变量可能带来的线程安全开销,这就是我正在寻找明确答案的要点 - 最好通过指向标准。
所以需要明确的是:我可以确保arr函数getVal()在编译时初始化,而不需要任何线程同步吗?
constexpr auto getArr()
{
std::array<int,10> arr;
for (int i = 0; i < 10; ++i) {
arr[i] = i*2;
}
return arr;
}
auto getVal(int i)
{
static constexpr auto arr = getArr();
return arr[i] + 1;
}
int main()
{
return …Run Code Online (Sandbox Code Playgroud) 我正在尝试了解在测试更改时我所看到的内容.该平台是带有GCC 4.8的openSUSE 42,但它可能会影响其他人.测试代码和错误如下.
$ cat test.cxx
#include <string>
#if (__cplusplus >= 201103L)
# define STATIC_CONSTEXPR static constexpr
# define CONSTEXPR constexpr
#else
# define STATIC_CONSTEXPR static const
# define CONSTEXPR
#endif
struct Name
{
STATIC_CONSTEXPR char* GetName() {return "XXX";}
};
int main(int argc, char* arv[])
{
const char* name = Name::GetName();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和:
$ g++ -O3 -std=c++11 test.cxx -o test.exe
test.cxx: In static member function ‘static constexpr char* Name::GetName()’:
test.cxx:13:44: warning: deprecated conversion from string constant to ‘char*’ …Run Code Online (Sandbox Code Playgroud) 如何检查值是否在即时创建的集中.我正在寻找一些语法糖,就像我们在python中一样
if s in set(['first','second','third','fourth']):
print "It's one of first,second,third,fourth";
Run Code Online (Sandbox Code Playgroud)
如何在C++中高效完成?