Moo*_*min 30 c++ pass-by-reference optional-parameters
我在C++中遇到了可选函数参数的问题
我要做的是编写带有可选参数的函数,该函数通过引用传递,这样我就可以用两种方式(1)和(2),但是(2)我真的不在乎什么是的价值mFoobar.
我试过这样的代码:
void foo(double &bar, double &foobar = NULL)
{
bar = 100;
foobar = 150;
}
int main()
{
double mBar(0),mFoobar(0);
foo(mBar,mFoobar); // (1)
cout << mBar << mFoobar;
mBar = 0;
mFoobar = 0;
foo(mBar); // (2)
cout << mBar << mFoobar;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但它崩溃了
void foo(double &bar, double &foobar = NULL)
Run Code Online (Sandbox Code Playgroud)
有消息:
error: default argument for 'double& foobar' has type 'int'
Run Code Online (Sandbox Code Playgroud)
没有函数重载可以解决它吗?
Pot*_*ter 39
不要对可选参数使用引用.没有引用NULL的概念:引用始终是特定对象的别名.
或许看看boost::optional或std::experimental::optional.boost::optional甚至专门用于参考类型!
void foo(double &bar, optional<double &> foobar = optional<double &>())
Run Code Online (Sandbox Code Playgroud)
In *_*ico 33
为什么不能使用函数重载?当然,这是解决您问题的最简单方法吗?
void foo(double &bar, double &foobar)
{
bar = 100;
foobar = 150;
}
void foo(double &bar)
{
double foobar = 0.0;
foo(bar, foobar);
}
Run Code Online (Sandbox Code Playgroud)
ken*_*ytm 30
(可变)引用的默认参数必须是l值.我能想到的最好,没有超载,是
static double _dummy_foobar;
void foo(double &bar, double &foobar = _dummy_foobar)
Run Code Online (Sandbox Code Playgroud)
要使用标准库安全地执行此操作,您需要std::optional结合使用std::reference_wrapper. 形式的可选引用std::optional<T&>在 C++17 中是非法的。
#include <optional>
#include <functional>
void foo(double& bar, std::optional<std::reference_wrapper<double>> foobar = {})
{
if(foobar) // If the user has passed a reference
{
foobar->get() = 1.0; // Assign values to the reference
}
}
Run Code Online (Sandbox Code Playgroud)
这对于被调用者来说是完全透明的。您可以像平常一样调用这样的函数:
double a {}, b {};
foo(b, a);
std::cout << a; // Prints 1.0;
Run Code Online (Sandbox Code Playgroud)
这种方法的优点是它有一个空值来指示用户是否确实传递了引用。使用-O2/-O3,它还可以非常巧妙地进行优化,并且没有运行时成本。
另一种方法是使用指针而不是引用.这提供了您想要的语义而不会重载.(就个人而言,我可能会超载.)
void foo(double* bar, double* foobar = 0)
{
if (bar) *bar = 100;
if (foobar) *foobar = 150;
}
// ...
foo(&mBar, &mFoobar);
// ...
foo(&mBar);
// ...
Run Code Online (Sandbox Code Playgroud)
这是另一种不会导致内存泄漏的疯狂方法,您在现实生活中永远不应该使用它,但乍一看似乎符合标准,并在 Cygwin 下使用 Visual C++ 2008 & g++ 3.4.4 进行编译:
void foo(double &bar, double &foobar = (*((double*)0)))
{
bar = 100;
double* pfoobar = &foobar;
if (pfoobar != 0)
foobar = 150;
}
Run Code Online (Sandbox Code Playgroud)
重申:不要这样做!有更好的选择!超载可以成为你的朋友!但是,是的,如果您既愚蠢又小心,就可以做到。:)