首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么时候应该在C++11中使用constexpr功能?

什么时候应该在C++11中使用constexpr功能?
EN

Stack Overflow用户
提问于 2011-01-20 22:07:06
回答 14查看 130K关注 0票数 365

在我看来,拥有一个“总是返回5的函数”是破坏或冲淡了“调用函数”的含义。这肯定是有原因的,或者需要这种功能,否则它就不会出现在C++11中,为什么会出现呢?

代码语言:javascript
运行
复制
// preprocessor.
#define MEANING_OF_LIFE 42

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

在我看来,如果我写了一个返回文字值的函数,然后我进行了代码审查,有人会告诉我,我应该声明一个常量值,而不是写return 5。

EN

回答 14

Stack Overflow用户

回答已采纳

发布于 2011-01-20 22:27:38

假设它做了一些更复杂的事情。

代码语言:javascript
运行
复制
constexpr int MeaningOfLife ( int a, int b ) { return a * b; }

const int meaningOfLife = MeaningOfLife( 6, 7 );

现在,您有了可以计算为常量的东西,同时保持良好的可读性,并允许比仅将常量设置为数字稍微复杂一些的处理。

它基本上为可维护性提供了很好的帮助,因为您正在做的事情变得越来越明显。以max( a, b )为例:

代码语言:javascript
运行
复制
template< typename Type > constexpr Type max( Type a, Type b ) { return a < b ? b : a; }

这是一个非常简单的选择,但它确实意味着如果您使用常量值调用max,它将在编译时显式计算,而不是在运行时计算。

另一个很好的例子是DegreesToRadians函数。每个人都发现度比弧度更容易读懂。虽然您可能知道180度是弧度的3.14159265 (Pi),但它写得更清楚,如下所示:

代码语言:javascript
运行
复制
const float oneeighty = DegreesToRadians( 180.0f );

这里有很多好的信息:

http://en.cppreference.com/w/cpp/language/constexpr

票数 325
EN

Stack Overflow用户

发布于 2015-03-03 07:51:17

引言

引入constexpr并不是为了告诉实现可以在需要常量表达式的上下文中求值;在C++11之前,一致性实现已经能够证明这一点。

实现无法证明的是某段代码的意图:

  • 开发人员想要用这个实体表达什么?
  • 我们是否应该盲目地允许在常量表达式中使用代码,因为它恰好可以工作?

如果没有constexpr,世界将会是什么样子?

假设您正在开发一个库,并意识到您希望能够计算区间(0,N]中每个整数的总和。

代码语言:javascript
运行
复制
int f (int n) {
  return n > 0 ? n + f (n-1) : n;
}

缺乏意图

如果传递的参数在翻译过程中是已知的,编译器可以很容易地证明上面的函数在常量表达式中是可调用的;但是您没有将其声明为一个意图-它只是碰巧是这样的。

现在,另一个人走过来,读取您的函数,执行与编译器相同的分析;“哦,这个函数可以在常量表达式中使用!”,并编写了以下代码。

代码语言:javascript
运行
复制
T arr[f(10)]; // freakin' magic

优化

作为一名“令人敬畏”的库开发人员,您决定f应该在调用时缓存结果;谁会想要一遍又一遍地计算同一组值?

代码语言:javascript
运行
复制
int func (int n) { 
  static std::map<int, int> _cached;

  if (_cached.find (n) == _cached.end ()) 
    _cached[n] = n > 0 ? n + func (n-1) : n;

  return _cached[n];
}

结果

通过引入愚蠢的优化,您刚刚打破了函数的每一个用法,恰好是在需要常量表达式的上下文中。

您从未承诺该函数在常量表达式中可用,如果没有constexpr,就无法提供这样的承诺。

那么,我们为什么需要constexpr呢?

constexpr的主要用法是声明意图。

如果一个实体没有被标记为constexpr -它从来没有打算在常量表达式中使用;即使它被标记了,我们也要依靠编译器来诊断这样的上下文(因为它忽略了我们的意图)。

票数 176
EN

Stack Overflow用户

发布于 2011-01-20 22:32:20

std::numeric_limits<T>::max()为例:无论出于什么原因,这都是一种方法。在这里,constexpr将是有益的。

另一个示例:您希望声明一个与另一个数组一样大的C数组(或std::array)。目前的方法是这样的:

代码语言:javascript
运行
复制
int x[10];
int y[sizeof x / sizeof x[0]];

但是,能够写出以下代码不是更好吗:

代码语言:javascript
运行
复制
int y[size_of(x)];

多亏了constexpr,您可以:

代码语言:javascript
运行
复制
template <typename T, size_t N>
constexpr size_t size_of(T (&)[N]) {
    return N;
}
票数 93
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4748083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档