constexpr和之间有什么区别const?
在我看来,拥有"总是返回5的功能"正在破坏或淡化"调用函数"的含义.必须有一个原因,或者需要这种能力,或者它不会出现在C++ 11中.为什么会这样?
// preprocessor.
#define MEANING_OF_LIFE 42
// constants:
const int MeaningOfLife = 42;
// constexpr-function:
constexpr int MeaningOfLife () { return 42; }
Run Code Online (Sandbox Code Playgroud)
在我看来,如果我编写了一个返回字面值的函数,并且我进行了代码审查,有人会告诉我,我应该声明一个常量值而不是写回返5.
以下定义之间有区别吗?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Run Code Online (Sandbox Code Playgroud)
如果没有,在C++ 11中首选哪种风格?
如果我有一个函数(比方说,一个大阵列)内的变量,它是有意义的声明它既static和constexpr?constexpr保证数组是在编译时创建的,那么它会static没用吗?
void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}
Run Code Online (Sandbox Code Playgroud)
static在生成的代码或语义方面,实际上是在做什么吗?
我想static const char在班上有一个数组.海湾合作委员会抱怨并告诉我应该使用constexpr,虽然现在它告诉我这是一个未定义的参考.如果我使数组成为非成员,那么它将编译.到底是怎么回事?
// .hpp
struct foo {
void bar();
static constexpr char baz[] = "quz";
};
// .cpp
void foo::bar() {
std::string str(baz); // undefined reference to baz
}
Run Code Online (Sandbox Code Playgroud) 使用C++ 11,Ubuntu 14.04,GCC默认工具链.
此代码失败:
constexpr std::string constString = "constString";
Run Code Online (Sandbox Code Playgroud)
错误:constexpr变量'constString'的类型'const string {aka const std :: basic_string}'不是文字...因为......'std :: basic_string'有一个非平凡的析构函数
是否有可能使用std::string的constexpr?(显然不是......)如果是这样,怎么样?是否有另一种方法在一个字符串中使用字符串constexpr?
在Scott Schurr 在CppCon上的"介绍constexpr"演讲的最后,他问"有没有办法毒害一个功能"?然后他解释说,这可以通过以下方式完成(尽管以非标准方式):
throw在constexpr功能extern const char*extern的throw我觉得我有点超出我的深度,但我很好奇:
考虑以下内联函数:
// Inline specifier version
#include<iostream>
#include<cstdlib>
inline int f(const int x);
inline int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
Run Code Online (Sandbox Code Playgroud)
和constexpr等效版本:
// Constexpr specifier version
#include<iostream>
#include<cstdlib>
constexpr int f(const int x);
constexpr int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:说明constexpr符是否意味着说明inline符,如果一个非常量参数传递给一个constexpr函数,编译器将尝试inline该函数,就像说明inline符被放入其声明一样?
C++ 11标准能保证吗?
我正在尝试在编译时计算字符串文字的长度.为此,我使用以下代码:
#include <cstdio>
int constexpr length(const char* str)
{
return *str ? 1 + length(str + 1) : 0;
}
int main()
{
printf("%d %d", length("abcd"), length("abcdefgh"));
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,程序打印4和8.由clang生成的汇编代码显示结果在编译时计算:
0x100000f5e: leaq 0x35(%rip), %rdi ; "%d %d"
0x100000f65: movl $0x4, %esi
0x100000f6a: movl $0x8, %edx
0x100000f6f: xorl %eax, %eax
0x100000f71: callq 0x100000f7a ; symbol stub for: printf
Run Code Online (Sandbox Code Playgroud)
我的问题:标准是否保证length函数将在编译时进行评估?
如果这是真的,编译时字符串文字计算的大门刚刚为我打开...例如,我可以在编译时计算哈希值等等......
让我先说明我的意图.在旧的(C++)时代,我们会有如下代码:
class C
{
public:
enum {SOME_VALUE=27};
};
Run Code Online (Sandbox Code Playgroud)
然后我们可以SOME_VALUE在整个代码中使用编译时常量,无论编译器在哪里看C::SOME_VALUE,它都只是插入文字27.
现在,将代码更改为以下内容似乎更为可接受:
class C
{
public:
static constexpr int SOME_VALUE=27;
};
Run Code Online (Sandbox Code Playgroud)
这看起来更清晰,提供SOME_VALUE了一个定义良好的类型,并且似乎是C++ 11中的首选方法.(至少对我来说不可靠)问题是,这也导致SOME_VALUE需要在外部进行的情况.也就是说,在某个地方的某个cpp文件中,我们需要添加:
constexpr int C::SOME_VALUE; // Now C::SOME_VALUE has external linkage
Run Code Online (Sandbox Code Playgroud)
导致这种情况的情况似乎是在使用const引用时SOME_VALUE,这在C++标准库代码中经常发生(请参阅本问题底部的示例).顺便说一句,我使用gcc 4.7.2作为我的编译器.
由于这种困境,我被迫恢复定义SOME_VALUE为枚举(即旧学校),以避免必须为某些(但不是所有)静态constexpr成员变量的cpp文件添加定义.是不是有某种方法告诉编译器这constexpr int SOME_VALUE=27意味着SOME_VALUE应该只将其视为编译时常量而不是具有外部链接的对象?如果您看到与它一起使用的const引用,请创建一个临时引用.如果你看到它的地址,如果需要的话就会产生编译时错误,因为它是编译时常量而已.
以下是一些看似良性的示例代码,它们使我们需要SOME_VALUE在cpp文件中添加定义(再次使用gcc 4.7.2进行测试):
#include <vector>
class C
{
public:
static constexpr int SOME_VALUE=5;
};
int main()
{
std::vector<int> iv;
iv.push_back(C::SOME_VALUE); // Will cause an undefined reference …Run Code Online (Sandbox Code Playgroud)