草庐IT

c++ - 真的需要 constexpr 吗?

coder 2023-06-02 原文

我一直在研究 C++ 的新 constexpr 功能,但我并不完全了解它的必要性。

例如下面的代码:

constexpr int MaxSize()
{
    ...

    return ...;
}

void foo()
{
    int vec[MaxSize()];
}

可以替换为:

int MaxSize()
{
    ...

    return ...;
}

static const int s_maxSize = MaxSize();

foo()
{
    int vec[s_maxSize];
}

更新

第二个示例实际上不是标准的 ISO C++(感谢一些用户指出这一点),但某些编译器(例如 gcc)支持它。因此,使程序有效的不是 const,而是 gcc 支持这种非标准特性的事实。 (据我所知,这只有在数组被定义为函数或方法的本地时才有可能,因为在编译时仍必须知道全局数组的大小。)如果我在没有选项 -std= 的情况下编译c++98 -pedantic-errors,连代码

int MaxSize()
{
    return 10;
}

void foo()
{
    int vec[MaxSize()];
}

将使用 gcc 编译。

因此,我将尝试重新表述我的问题,同时考虑到目前收到的反馈(以及我在此期间完成的一些进一步阅读)。

我大量使用 const 关键字。使用 const 我可以定义一个在其整个生命周期内具有特定值的常量。可以使用任何表达式初始化常量,该表达式只计算一次,即在创建常量时。对于这些情况,我认为 constexpr 非常没用:它会引入一个非常小的优化,因为定义常量值的表达式将在编译时而不是运行时计算。每次我需要一个带有复杂初始化的运行时常量时,我​​都会使用关键字 const

所以 constexpr 在我们需要在编译时初始化一个常量的情况下可能会派上用场。一个例子是 vector 定义:标准不支持在运行时定义大小。另一个例子是带有一个或多个非类型参数的模板。

在这种情况下,我通常使用宏:

#define MAX_SIZE (10)

void foo()
{
    int vec[MAX_SIZE];
}

但是,如果我理解正确的话,constexpr 函数比宏更强大,因为它们允许在其定义中递归调用 constexpr 函数。但是,我想不出任何实际应用中我曾经想使用如此复杂的计算来定义编译时常量。

因此,即使它可能是一个有趣的功能,我仍然想知道是否需要它(即它多久可以解决宏不够用的情况)。也许看看一些无法用宏解决的现实例子会帮助我改变这种看法。

最佳答案

int vec[s_maxSize]; 在第二个例子中实际上是非法的,所以这在 C++ 中是不可能的。但是你的第一个例子是完全合法的 C++0x。

这就是你的答案。你实际上不能做你在 C++ 中提出的建议。它只能在 C++0x 中使用 constexpr 来完成。

我还想指出,这段代码也适用于 C++0x。在 C++ 中执行此操作需要一些非常精美的类模板。

constexpr unsigned int gcd(unsigned int const a, unsigned int const b)
{
   return (a < b) ? gcd(b, a) : ((a % b == 0) ? b : gcd(b, a % b));
}

char vec[gcd(30, 162)];

当然,在 C++0x 中,您仍然必须使用三元运算符而不是 if 语句。但是,它可以工作并且仍然比您在 C++ 中强制使用的模板版本更容易理解:

template <unsigned int a, unsigned int b>
class gcdT {
 public:
   static unsigned int const value = gcdT<b, a % b>::value;
};

template <unsigned int a>
class gcdT<a, 0> {
 public:
   static unsigned int const value = a;

};

char vec[gcdT<30, 162>::value];

当然,在 C++ 中,如果您需要在运行时进行计算,您仍然必须编写 gcd 函数,因为模板不能与在运行时变化的参数一起使用.并且 C++0x 将有额外的优化提升,因为知道函数的结果完全由传入的参数决定,这是只能用 C++ 中的编译器扩展来表达的事实。

关于c++ - 真的需要 constexpr 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6016771/

有关c++ - 真的需要 constexpr 吗?的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  4. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  5. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. ruby-on-rails - 需要帮助最大化多个相似对象中的 3 个因素并适当排序 - 2

    我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night

  9. ruby - 我需要从 facebook 游戏中抓取数据——使用 ruby - 2

    修改(澄清问题)我已经花了几天时间试图弄清楚如何从Facebook游戏中抓取特定信息;但是,我遇到了一堵又一堵砖墙。据我所知,主要问题如下。我可以使用Chrome的检查元素工具手动查找我需要的html-它似乎位于iframe中。但是,当我尝试抓取该iframe时,它​​是空的(属性除外):如果我使用浏览器的“查看页面源代码”工具,这与我看到的输出相同。我不明白为什么我看不到iframe中的数据。答案不是它是由AJAX之后添加的。(我知道这既是因为“查看页面源代码”可以读取Ajax添加的数据,也是因为我有b/c我一直等到我可以看到数据页面之后才抓取它,但它仍然不存在)。发生这种情况是因为

  10. ruby - 需要重构为新的 Ruby 1.9 哈希语法 - 2

    这个问题在这里已经有了答案:HashsyntaxinRuby[duplicate](1个回答)关闭5年前。我有一个Recipe,其中包含以下未通过lint测试的代码:service'apache'dosupports:status=>true,:restart=>true,:reload=>trueend失败并出现错误:UsethenewRuby1.9hashsyntax.supports:status=>true,:restart=>true,:reload=>true不确定新语法是什么样的...有人可以帮忙吗?

随机推荐