44

C++ のオプションの関数パラメーターに問題があります

私がやろうとしているのは、参照によって渡されるオプションのパラメーターを使用して関数を記述して、(1) と (2) の 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;
}

しかし、それはでクラッシュします

void foo(double &bar, double &foobar = NULL)

メッセージ付き:

error: default argument for 'double& foobar' has type 'int'

関数のオーバーロードなしで解決できますか?

4

12 に答える 12

45

オプションのパラメーターには参照を使用しないでください。参照 NULL の概念はありません。参照は常に特定のオブジェクトへのエイリアスです。

boost::optionalまたはを参照してくださいstd::experimental::optionalboost::optional参照型にも特化しています!

void foo(double &bar, optional<double &> foobar = optional<double &>())
于 2010-05-12T05:57:20.063 に答える
44

関数のオーバーロードを使用できないのはなぜですか? 確かにそれはあなたの問題に対する最も簡単な解決策ですか?

void foo(double &bar, double &foobar) 
{ 
   bar = 100; 
   foobar = 150; 
}

void foo(double &bar) 
{ 
   double foobar = 0.0;
   foo(bar, foobar);
}
于 2010-05-12T05:56:42.137 に答える
41

(変更可能な) 参照の既定の引数は、左辺値でなければなりません。オーバーロードせずに私が考えることができる最高のものは

static double _dummy_foobar;
void foo(double &bar, double &foobar = _dummy_foobar)
于 2010-05-12T05:53:57.867 に答える
9

これを行う別の方法は、参照の代わりにポインターを使用することです。これにより、オーバーロードせずに必要なセマンティクスが提供されます。(個人的には、おそらくオーバーロードを使用します。)

void foo(double* bar, double* foobar = 0)
{
   if (bar) *bar = 100;
   if (foobar) *foobar = 150;
}

   // ...

   foo(&mBar, &mFoobar);

   // ...

   foo(&mBar);

   // ...
于 2010-05-12T06:00:58.147 に答える
5

これはメモリ リークを引き起こさないもう 1 つのクレイジーな方法です。実際には使用しないでください。ただし、一見すると標準に準拠しているように見え、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;
}

繰り返しますが、これをしないでください。より良いオプションがあります!過負荷はあなたの友達になることができます!しかし、ええ、あなたが愚かで慎重であれば、それを行うことができます. :)

于 2011-03-23T18:15:42.960 に答える
2

std::optional標準ライブラリでこれを安全に行うには、 と組み合わせて使用​​する必要がありますstd::reference_wrapperstd::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
    }
}

これは、呼び出し先に対して完全に透過的です。このような関数は、通常どおり呼び出すことができます。

double a {}, b {};
foo(b, a);
std::cout << a; // Prints 1.0;

このアプローチの利点は、ユーザーが実際に参照を渡したかどうかを示す null 値があることです。-O2/-O3 を使用すると、ランタイム コストがかからずに、きれいに最適化されます。

于 2021-06-21T14:14:35.713 に答える
1

参照パラメーターのデフォルト/オプション値を設定するよりも、ポインター型を使用して NULL に設定する方がはるかに簡単です。

于 2012-05-31T21:57:51.810 に答える
-4

あなたはこのクレイジーな方法を行うことができます:

void foo(double &bar, double &foobar = (*(new double())))

PS-私はそれが楽しいものではないが、その方法を知っています。また、メモリリークを残さないように注意してください。:))

于 2010-05-12T05:59:33.283 に答える