【问题标题】:C++ Default argument for vector<int>&?向量<int>&的C++默认参数?
【发布时间】:2011-03-10 00:05:05
【问题描述】:

我有一个函数,

void test( vector<int>& vec );

如何设置 vec 的默认参数? 我试过了

void test( vector<int>& vec = vector<int>() );

但是有一个警告“使用了非标准扩展:'默认参数':从 'std::vector<_ty>' 转换为 'std::vector<_ty> &'”

有没有更好的方法来做到这一点?而不是

void test() {
    vector<int> dummy;
    test( dummy );
}

问候, 投票站

【问题讨论】:

    标签: c++ arguments


    【解决方案1】:

    你试过了吗:

    void test(const vector<int>& vec = vector<int>());
    

    C++ 不允许将临时对象绑定到非常量引用。

    如果您真的需要vector&lt;int&gt;&amp;(而不是const),您可以声明一个静态实例并将其用作默认(因此非临时)值。

    static vector<int> DEFAULT_VECTOR;
    
    void test(vector<int>& vec = DEFAULT_VECTOR);
    

    但请注意,因为 DEFAULT_VECTOR 将(可以)被修改并且不会在每次调用时重置!不确定这是否是您真正想要的。


    感谢stinky472,这是一个线程安全的替代方案:

    与其提供默认值,不如使用调用另一个版本的零参数版本重载 test()

    void test()
    {
      vector<int> vec;
      test(vec);
    }
    

    【讨论】:

    • +1 但我认为应该指出,如果要修改此“DEFAULT_VECTOR”,“测试”通常不是线程安全的。这可能很乏味,但我强烈建议为这种需求编写两个函数(一个可以重用另一个): void test() {vector temp;测试(温度); }
    • 附带说明,如果您可以在后者上使用某种方法来返回对自身的此类引用,则有一种获取临时引用的方法......例如operator=。所以,void test(vector&lt;int&gt;&amp; vec = vector&lt;int&gt;().operator=(vector&lt;int&gt;())); 应该可以工作(临时的生命周期在这里不受影响,并且足以处理呼叫)。但请不要这样做:)
    • 感谢您的回答。但我不明白为什么 DEFAULT_VECTOR 应该是静态的。你能解释一下吗?
    【解决方案2】:

    我发现非const 引用参数具有默认值是有问题的。这是什么意思?

    通常,采用非const 引用的函数意味着“我可能会更改参数”。如果参数是可选,为什么不传递(非const)指针?这样,当调用者不想传递参数时,他们可以传递NULL
    (有关如何传递函数参数的更多信息,请参阅 here。)

    编辑:嗯,当然,还有重载。只需添加另一个不接受此参数的重载。

    【讨论】:

    • @DeadMG:你是指我损坏的语法子系统吗?
    • 我会这样做吗?
    【解决方案3】:

    我知道这个问题是在 2010 年提出的,但对于 C++11,您可以这样做:

    void test( vector<int>& vec = {}) {
          // Awesome code here
    }
    

    正如this answer 中指出的那样。

    【讨论】:

    • 这与问题中的void test( vector&lt;int&gt;&amp; vec = vector&lt;int&gt;() ); 具有相同的含义,由于尝试将临时绑定到非常量引用,这是非法的。在您链接到的答案中,它不是参考。
    【解决方案4】:

    我们无法初始化对临时对象的可变引用。只有 const 引用允许这样做。你所追求的很可能是这样的:

    void test( const vector<int>& vec = vector<int>() );
    

    除了避免未定义的行为之外,这在逻辑上和从 const 正确性的角度来看是最有意义的。如果您希望“测试”修改传递给它的原始向量,您将无法明智地提供默认值。因此很明显,您在此处使用 'vec' 是出于只读目的,因此应将其设为 const 引用。

    【讨论】:

    • 您不能直接初始化对临时对象的可变引用,期间。临时不会绑定到对非常量的引用 - 如果您尝试这样做,它不是 U.B.,它是格式错误的输入(即编译器错误)。 VC++ 允许您这样做,但正确地指出它是一种语言扩展。
    • @Pavel 好点!我见过允许这种行为的讨厌的编译器,比如 MSVC 和 CodeWarrior 的过去版本,其中代码构建但崩溃了。为了准确起见,我将相应地修改帖子。感谢您指出。
    【解决方案5】:

    您可以只传递一个指向向量的指针并将其初始化为 NULL

    void test( vector<int>* vec = NULL );
    

    【讨论】:

      【解决方案6】:

      我知道这个问题是在大约 10 年前提出的。但是对于现在找到解决方案的任何人,我已经为您准备好了。我基本上有三种不同的方法:

      void test(vector<int>vec = vector<int>(10, 0){//definition}
      

      如果默认向量具有给定大小和公共初始化器值,则可以使用它。

      void test(vector<int>vec = vector<int>{1, 2, 3, 4}){//definition}
      

      如果默认向量具有给定大小和不同的初始化器值,则可以使用它。

      另一种方法是将全局矢量对象定义为:

      vector<int> globalvector;
      

      (已初始化或未初始化)并将此对象作为默认值传递为

      void test(vector<int>vec = globalvector){//definition}
      

      最后一个的一个重要好处是它可以更好地控制默认值本身,因为函数可用于在控制到达test() 函数之前将值分配给此globalvector。另一个好处是(据我所知),如果函数涉及通过引用传递,它的工作原理和以下一样:

      void test(vector<int>& vec = globalvector){//definition}
      

      不同于前两者。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-07
        • 1970-01-01
        • 1970-01-01
        • 2010-12-01
        • 1970-01-01
        • 2012-02-29
        • 1970-01-01
        相关资源
        最近更新 更多