使用具有默认值的参考参数是一种良好的做法

Is using a reference parameter with default value good practice?

本文关键字:一种 默认值 参考 参数      更新时间:2023-10-16

我有以下代码:

#include <string>
#include <iostream>
void f(const std::string& s = "")
{
  std::cout << """ << s << """ << std::endl;
}
int main()
{
  std::string s1 = "qwe";
  f();
  f("asd");
  f(s1);
}

有临时参数和没有参数的调用有多糟糕(如果有的话)?

据我所知,这种编译只是因为const引用延长了临时的生命,直到方法结束http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

尝试在s参数旁边没有const的情况下编译相同的示例失败。

#include <string>
#include <iostream>
void f(std::string& s = "")
{
  std::cout << """ << s << """ << std::endl;
}
int main()
{
  std::string s1 = "qwe";
  f();
  f("asd");
  f(s1);
}

编译

g++-5 -O3 -Wall --std=c++11 main.cpp  && ./a.out
main.cpp:4:27: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
 void f(std::string& s = "")
                           ^
In file included from /usr/include/c++/5/string:52:0,
                 from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note:   after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
       ^
main.cpp: In function ‘int main()’:
main.cpp:12:5: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
   f();
     ^
In file included from /usr/include/c++/5/string:52:0,
                 from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note:   after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
       ^
main.cpp:4:6: note: in passing argument 1 of ‘void f(std::string&)’
 void f(std::string& s = "")
      ^
main.cpp:13:10: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
   f("asd");
          ^
In file included from /usr/include/c++/5/string:52:0,
                 from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note:   after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
       ^
main.cpp:4:6: note:   initializing argument 1 of ‘void f(std::string&)’
 void f(std::string& s = "")

这不是一种可怕的做法,但通常最好提供重载:

void f(std::string const& s) { std::cout << "\" << s << "\n"; }
void f() { f(""); }

它避免了一些最终会让很多人感到困惑的语言功能。例如,这个打印什么?

struct base { virtual void f(int i = 42) { std::cout << i; } };
struct derived : base { void f(int i = 19) { std::cout << i; }};
int main() { base * b = new derived(); b->f(); }

当您使用默认参数时也会出现歧义错误,而当您使用重载时则不会。

就const引用而言,这其实并不重要。默认值在函数调用的生存期内绑定到引用。真的一点效果都没有。当编译器可以执行某些引用参数无法执行的优化时,使用值可能会得到更好的结果,但通常情况下,这并不值得关注。

当然,这不适用于非常量引用,因为它们不绑定到临时引用。

默认值允许您在没有任何参数的情况下调用函数,因此如果您有时不将参数传递给函数,请使用具有默认值的引用参数,否则就没有必要这样做。

相关文章: