1

重複の可能性:
C++ の可変数の引数?

引数の数が可変の関数の引数の数を設定できませんか? 例として、次のインターフェースを実装できますか?

int sum(...) { ... }

sum(1, 2, 3, 4); // return 10
4

5 に答える 5

3

従来の可変個引数関数は面倒でタイプ セーフではありませんが、C++11 では可変個引数テンプレートと (コンパイル時の) 再帰を使用してこれをきれいに行うことができます。

// Base case for recursion
template <typename T>
inline T sum(T n) {
  return n;
}

// Recursive case
template <typename T, typename... Args>
inline T sum(T n, Args... args) {
  return n + sum(args...);
}

これはテンプレートであるため、次のようにoperator+定義されているすべてのタイプで機能します。

std::cout << sum(1, 2, 3) << std::endl;  // Prints 6
std::cout << sum(3.14, 2.72) << std::endl;  // Prints 5.86

ただし、再帰テンプレート関数の戻り値の型は最初の引数のみから取得されるため、1 回の呼び出しで異なる引数の型を混在させると、驚くべき結果が得られます。 sum(2.5, 2)期待どおり 4.5 が返されsum(2, 2.5)ますが、戻り値の型がintであるため 2 が返されますdouble。派手にしたい場合は、新しい代替関数構文を使用して、戻り値の型が の自然な型であることを指定n + sum(args...)できます。

// Recursive case
template <typename T, typename... Args>
inline auto sum(T n, Args... args) -> decltype(n + sum(args...)) {
  return n + sum(args...);
}

現在sum(2.5, 2)sum(2, 2.5)両方とも 4.5 を返します。

実際のロジックが合計よりも複雑で、インライン化したくない場合は、インライン テンプレート関数を使用して、すべての値をある種のコンテナー ( astd::vectorまたは などstd::array) に入れ、それを非インラインに渡すことができます。最後に実際の作業を行う関数。

于 2012-07-17T00:07:30.983 に答える
1

vector<int>おそらくこれを行うには、波括弧付きの初期化子リストを使用してオンザフライで構築するa のようなものを取る関数を記述します。

int sum(std::vector<int> const &n) { 
    return std::accumulate(begin(n), end(n), 0);
}

数値が(たとえば)代わりに浮動小数点である可能性がある場合は、代わりにテンプレートとして書きたいと思うでしょう:

template <class T>
T sum(std::vector<T> const &n) { 
   return std::accumulate(begin(n), end(n), T());
}

いずれにせよ、これをわずかに異なる方法で呼び出すことになります。

int x = sum({1,2,3,4});

警告: この機能はかなり最近 C++ に追加されたため、一部のコンパイラ (VC++ など) はまだサポートしていませんが、他のコンパイラ (g++ 4.7+ など) はサポートしています。

于 2012-07-16T23:21:58.493 に答える
0

いいえ、できません。

可変引数を使用しないでください。彼らは考えられるありとあらゆる方法を吸収し、誰の時間にもまったく価値がありません。

于 2012-07-16T23:13:39.807 に答える
0

C++ 可変個引数関数は、渡された引数の数 (および型) を認識している必要があります。たとえば、printf のフォーマット文字列は、期待される追加の引数を示します。

4 つの int を取得したか 10 を取得したかを知る方法sumはありません。最初の引数を長さにすることができます。

int sum(int howmany, ...) { ... }

そのため、関数は int がいくつ続くかを知っています。しかし、実際には、配列 (または C++ っぽい場合はベクトル) を渡す必要があります。

于 2012-07-16T23:13:52.553 に答える
0

問題を解決するには複数の方法があります。いくつか説明します。

方法 1: -必要に応じて一連のオーバーロードされた合計関数を作成します。

短所 - コードの肥大化

これは、ヘッダーを使用して複数の関数を作成することで実装できます。

int sum(int a);
int sum(int a, int b);
int sum(int a, int b, int c);

等...

方法 2: - リンク リストを使用してカスタム クラスを作成し、リンク リストの先頭へのポインターを渡します。渡されるデータの量がわからない場合は、これがおそらく最善の方法です。

関数ヘッダー:

int sum(LinkedList *headPointer);

方法 3: -変数の配列を渡す

関数ヘッダー:

int sum(int input[]);

方法 4: -自動設定変数を使用して関数を作成する

関数ヘッダー:

int sum(int a=0, int b=0, int c=0, int d=0,... int n=0);
于 2012-07-16T23:14:36.267 に答える