【问题标题】:Why existing function arguments cannot be used to evaluate other default arguments?为什么现有的函数参数不能用于评估其他默认参数?
【发布时间】:2012-02-27 03:19:01
【问题描述】:

我正在编写一个函数foo(),它接受2 个const char*s 作为参数,pBeginpEndfoo() 传递了一个以空字符结尾的字符串。默认情况下,pEnd 指向字符串的\0(最后一个字符)。

void foo (const char *pBegin,
          const char *pEnd = strchr(pBegin, 0))  // <--- Error
{
  ...
}

但是,我在上面的行中收到错误:

error: local variable ‘pBegin’ may not appear in this context

为什么编译器不允许这样的操作?潜在的问题是什么?

【问题讨论】:

  • 不同的调用约定以不同的顺序推送参数。一些典型的(cdeclstdcall)从右向左推,所以在你的例子中,pEnd 需要在pBegin 之前进行评估,我认为这没有意义......有一个小测验这里:en.wikipedia.org/wiki/X86_calling_conventions

标签: c++ function compiler-errors language-lawyer default-arguments


【解决方案1】:

该标准不仅明确禁止在默认参数表达式中使用其他参数,还解释了原因并举例说明:

ISO/IEC 14882:2003(E) - 8.3.6 默认参数 [dcl.fct.default]

9. 每次调用函数时都会评估默认参数。 未指定函数参数的求值顺序。 因此,默认情况下不应使用函数的参数 参数表达式,即使它们没有被评估。 在默认参数表达式之前声明的函数在范围内 并且可以隐藏命名空间和类成员名称。 [例子:

    int a;
    int f(int a, int b = a);         // error: parameter a
                                     // used as default argument
    typedef int I;
    int g(float I, int b = I(2));    // error: parameter I found
    int h(int a, int b = sizeof(a)); // error, parameter a used
                                     // in default argument

——结束示例] ...

【讨论】:

  • 最后一个例子可能看起来过于严格。无论 a 的值如何,我们都知道 sizeof(a) == sizeof(int)。评估顺序的参数不适用,因此这种情况可以被允许。但是 g++ 4.8.2 引发了预期的错误。我想这是为了保持规则简单。
【解决方案2】:

该语言仍然提供了一种方法来做你想做的事 - 使用重载函数:

void foo (const char *pBegin, const char *pEnd)
{
   //...
}

void foo (const char *pBegin)
{ foo(pBegin, strchr(pBegin, 0)); }

【讨论】:

    【解决方案3】:

    当函数被调用时,默认参数被计算,但它们被计算的顺序不是由 C++ 标准定义的。这意味着您不能在默认参数中引用其他参数,因为它们可能还没有已知值。

    【讨论】:

      【解决方案4】:

      您不能在默认参数值中使用局部变量。

      Quote from here:

      标准告诉我们,默认参数只是一个表达式。 有些事情是不允许的(使用局部变量,使用 关键字'this'),但几乎所有其他东西都可以作为默认值 论据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        • 2022-11-14
        • 1970-01-01
        • 2014-07-18
        相关资源
        最近更新 更多