【问题标题】:Using static/global variables as default arguments使用静态/全局变量作为默认参数
【发布时间】:2017-02-01 13:21:26
【问题描述】:

在处理具有默认参数按值传递的方法/函数时,我想出了一个解决方案,但我不确定它是否会出现问题。

当期望的行为是将单个值作为默认参数时,只需指定一个值就足够了:

void foo(type arg=value)
{
    //do something using arg...
}

但是,例如,当期望的行为是生成一个随机值时,情况就不同了。在这种情况下,为了生成一个随机值,我想出了给定的解决方案:

static type DEFAULT = /* value */; //static is optional, DEFAULT can be any name.
void foo(const type& arg=DEFAULT)
{
    type x;
    if(&arg == &DEFAULT)
        x = generate_random();
    else x = arg;
    // also we could use a ternary like
    // type x = (&arg == &DEFAULT? generate_random() : arg) 

    // do something with x...
}

使用这种方法有什么缺点吗?可以安全地将引用的地址与给定的默认参数的地址进行比较吗?这也适用于方法和静态类变量吗?

其他一些解决方案是:

使用附加签名重载:

void foo(){ /* do something using a random value */  }

void foo(type arg){ /* do something using arg... */ } 

或者也许是 pointers,默认 arg 为 null:

void foo(type* arg=null) { /* if arg is null, generate value.  */ }

【问题讨论】:

  • 在你的情况下,如果没有传递参数,重载函数不是更好吗?的确,这是应该做的。默认值是默认值,而不是默认行为。
  • @GabrielVasconcelos 我明白你的意思。但是,我已经看到函数接收指针并在传递空指针时具有不同的行为(不仅仅是抛出异常)。 SDL's FillRect 函数在将 NULL 传递给其第二个参数时的行为略有不同。

标签: c++ static parameter-passing pass-by-reference default


【解决方案1】:

我不明白你为什么要把它弄得这么复杂。作为此功能的用户,我不希望它像现在这样工作。如果签名是

void foo(const type& arg=DEFAULT);

那么我希望以下两个调用是等效的:

foo();
type x = DEFAULT;
foo(x);

问题是不要取参考地址。引用只是原始变量的别名。问题是您期望变量DEFAULT 而不是它的值。这不是函数参数的预期工作方式(即使它是通过引用传递)。

顺便说一句,上面的例子不是太做作。试想一下,我想将参数放入向量中,然后为向量中的每个元素调用函数。使用您当前的方法,我无法将 DEFAULT 放入向量中并将其传递给函数。实际上更糟糕的是:我可以做到,但它不会达到我的预期。

在这种特殊情况下,我会像这样简单地实现它:

void foo(T arg = 0, bool generateRandom = true) {
    T x;
    if(generateRandom) x = generate_random();
    else x = arg;

    // do something with x...
}

那么可以这样调用:

foo(3.5,false); // uses the value
foo();          // generates a random value

【讨论】:

  • 名称 DEFAULT 只是一个例子。可以选择它来避免名称冲突。
  • will not be recognized as DEFAULT。这实际上是有意的。如果指定了一个值,它应该表现得好像用户已经指定了一个值。
  • @Hydren 好吧,然后我误解了 sn-p。但是,我仍然不明白您为什么要使其复杂化。如果他希望函数使用一个随机生成的值,让用户传递一个随机生成的值会不会更容易?如果我是用户,我希望能够检查所使用的随机值。
  • @Hydren 改了答案,其实我的论点还是一样,不要这样做;)
  • 我的意思是:如果我传递默认变量,我会得到默认行为,但是如果我传递默认值(当我将默认变量推送到容器中时就是这种情况),那么我不要得到默认行为。这不仅可读性差,而且非常令人困惑,恕我直言
猜你喜欢
  • 2013-12-13
  • 1970-01-01
  • 2017-07-31
  • 2015-01-27
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
相关资源
最近更新 更多