【问题标题】:Is it possible to use default arguments and a variable number of arguments in a single function?是否可以在单个函数中使用默认参数和可变数量的参数?
【发布时间】:2011-08-16 01:52:26
【问题描述】:

例如,像这样的:

#include <cstdarg>

void my_function(int it=42, ...)
{
     /* va_list/start/arg/end code here */
}

以上代码在 C++ 中究竟是什么意思?它在 G++ 中编译得很好。请注意,我无法想象在任何情况下这都会有用,甚至无法想象它应该做什么。我只是好奇。

【问题讨论】:

    标签: c++ variadic-functions default-arguments


    【解决方案1】:
    void my_function(int it=42, ...)
    

    你说这个函数用 GCC 编译得很好,但是你不能使用默认参数,你还必须为所谓的默认参数传递参数,才能使用这个函数。

    my_function("string", 98, 78, 99); //error
    my_function(898, "string", 98, 78, 99); //ok, but the param 'it' becomes 898
    

    问问自己:

    第一个参数898是对应于参数it还是对应于可变参数(并且你打算为it使用默认值42)?

    编译器无法知道你的意图!

    顺便说一句,@Johannes 指出了一个好点:您可以简单地调用my_function() 而无需传递任何参数。这是我看到的唯一可以使用默认参数的实例。


    现在如果你改变默认参数的位置,像这样:

    void f(..., int p = 10); //illegal
    

    那么这在 C++ 中是非法的。

    再次问问自己:如果允许,那么您可以将其称为:

    f(9879, 97897, 7897);
    

    最后一个参数7897是对应参数p还是对应可变参数(并且你打算使用10的默认值p)?

    在这种情况下编译器也无法知道你的意图。

    【讨论】:

    • 为什么不能说my_function();?此外,您似乎在最后一行中说声明是有效的,但在您回答的第一部分中说您不能声明 my_function。你能澄清一下吗?
    • 我在 C++03 标准中没有发现有问题的声明是非法的。在 C++11 中,它看起来是合法的:第 8.3.6 节“默认参数”的一个例子说void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow a parameter with a default argument。你的回答似乎误导了我。
    • @Alexey:如果你投了我的反对票,那完全没有道理,因为我从未说过相关声明是非法的。 :-)
    • @Nawaz 你的回答说的有些不同。在我看来如何:您首先认为 void f(int = 0, ...) 是非法的,然后尝试使用 GCC,发现它接受这样的。但是您忘记更新以前的文本,仍然显示“由于默认参数必须从最右边的参数开始,所以这是不可能的......因此你想要的东西是不可能的。”。我同意@Alexey,这看起来很混乱。
    • 不,我没有投反对票;我为什么要?但是,Alessandro 询问这段代码的含义,您回答“否”并试图解释为什么默认参数不能与省略号一起使用。查尔斯的回答更重要,我赞成。
    【解决方案2】:

    是的,这个函数声明在技术上没有任何问题,尽管我不推荐这种做法,因为它很容易出错,编译器在调用函数时无法警告。

    您可以在第一个具有默认参数的参数处停止提供参数。如果你让默认参数接管,那么变量参数列表当然是空的。

    您可以提供命名参数之外的参数,以便填充变量参数列表,在这种情况下,将不使用任何默认参数。

    正如您所指出的,是否存在实际有用的实际情况是另一个问题。

    【讨论】:

      【解决方案3】:
      void my_function(int it=42, ...){ /* va_list/start/arg/end code here */}
      

      嗯,代码应该完全按照它的样子做。传递的第一个参数(如果有)是参数it,其余的是...。因此,如果您不传递任何参数,那么您的 it 参数将被分配默认值 (42),而 it(等于 42)是传递给函数的唯一参数。

      这样的代码可能很有用,就像...-terminated argument-list 在类似情况下的任何其他用法一样(并且风险具有相同的性质)。

      例子:

      你可以创建函数:

      // DECLARATION:
      // returns vector filled with items specified
      std::vector<float> float_vector( size_t item_count = 0, ... /* floats */ );
      
      // DEFINITION:
      std::vector<float> float_vector( size_t item_count, ... )
      {
          std::vector<float> vec;
          va_list ap;
      
          va_start(ap, item_count);
          for( ; item_count > 0; --item_count )
          {
              vec.push_back( va_arg(ap,float) );
          }
          va_end(ap);
          return vec;
      }
      

      显然float_vector() 返回空向量,因为它等同于float_vector(0)。在所有其他情况下,float_vector 的行为与具有可变数量参数的普通函数一样。

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 2020-10-27
        • 1970-01-01
        • 2014-07-30
        • 1970-01-01
        • 1970-01-01
        • 2015-05-19
        相关资源
        最近更新 更多