下面是我的代码:
class test {
public:
constexpr test() {
}
constexpr int operator+(const test& rhs) {
return 1;
}
};
int main() {
test t; //constexpr keyword isn't necessary
constexpr int b = t+test(); // works at compile time!
int w = 10; // ERROR constexpr required
constexpr int c = w + 2; // Requires w to be constexpr
return 0;
}
我注意到,即使我没有将test指定为constexpr
,它也能正常工作。我尝试通过对int
执行相同操作来复制结果,但我得到了错误。具体来说,它希望constexpr int c = w + 2;
中的int w
为constexpr
。在我第一次尝试使用test
时,是否因为我已经在构造函数上使用了constexpr
,所以它工作了?如果是这样,那么,假设所有具有constexpr
构造函数的类将导致所有用这些构造函数示例化或创建的对象都是constexpr
,这是正确的吗?
附加问题:
如果我有一个constexpr
构造函数,那么像test* t = new test();
这样做是不是不好?
3条答案
按热度按时间ds97pgxw1#
有一个constexpr构造函数并不会自动声明该变量为constexpr,所以
t
不是constexpr.在这个例子中,你正在调用一个constexpr函数,这一行:可以如下所示:
那么接下来的问题是
test()
是否是常量表达式,这是因为构造函数是constexpr,并且不属于C++11标准草案章节5.19
[expr. const] 段落2
中的任何例外,该段落中写道:一个条件表达式是一个核心常量表达式,除非它包含下列之一作为可能求值的子表达式[...]
并包括以下项目符号:
[...]
通过引入成员变量
x
对test
做一些小的修改,我们可以更容易地看到这一点:尝试在
operator +
中访问它,我们可以看到下面的行现在失败了:clang(* see it live *)中出现以下错误:
失败的原因是
t
不是constexpr变量,因此其子对象也不是constexpr变量。第二个例子:
不起作用,因为它属于C++11标准草案章节
5.19
[expr. const] 中的一个例外:[...]
6xfqseft2#
constexpr
构造函数对类类型的影响可以在C++标准中读取3.9类型
(...)
(...)
因此
constexpr
构造函数意味着可以执行静态初始化,并且可以使用this one:test
是一个 * literal类*这一事实并不意味着它的所有示例都是常量表达式:Demo
在上面的例子中,示例
a
没有声明为常量,所以即使a
可以是constexpr
常量,它也不是常量(因此可以修改)。7vhp5slm3#
在我的实验中,constexpr关键字或多或少地指示编译器,它必须能够静态解析该调用中给出的所有代码路径。(看起来是这样的),所有东西都必须声明为constexpr,否则会失败。例如,在你的代码中,如果你没有声明constexpr操作符或构造函数constexpr,那么初始的constexpr赋值给B将会失败。看起来constexpr只有在你赋值给一个声明为constexpr的变量时才有效。否则,它似乎只能作为编译器的建议,说明代码路径可以通过静态求值进行优化,但如果您没有使用constexpr变量赋值显式地指示它,它就不能保证能够做到这一点。
也就是说,声明构造函数constexpr在正常情况下似乎没有任何影响。下面的机器码是用下面的命令行生成的:
所以你的B赋值语句会产生这样的代码:
但是,如果删除B变量上的constexpr声明:
看起来好像操作符和构造函数没有被声明为constexpr一样,但实际上,在这种情况下,您应该参考编译器的细节。