10

標準 C++ ライブラリで次のベクター コンストラクターを確認しました。

explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());

2 番目のコンストラクターがマークされていない理由はありexplicitますか? これはコンパイルされ、気分が悪くなります

void f(vector<string>);

int main() {
  f({10, "foo"});
}

を省略する"foo"とコンパイルされず、文字列のベクトルを必要とする関数に int と文字列のペア (複合) 値を渡すと、それが期待されます。

4

3 に答える 3

3

{ ... }一時的なものを作成するときに常にコンテナ要素のリストを表すと期待するのがそもそも正当であるかどうか疑問に思っています。これはあなたの仮定のようです。IMO 1 つの引数のコンストラクターは、次のような不要な変換シーケンスや無意味な代入を避けるために宣言する必要があります。explicit

vector<int> x = 3;

一方、引数が 2 つのバージョンでは、テンポラリが作成されたときにこのコンストラクタを呼び出すことができる唯一の方法は中かっこを使用することであり、プログラマはそこに何を入れているかを十分に認識しています。たとえば、 と は文字列ではないため、コンテナー要素のリストを表すことを意図していないことは10明らかです。"hello"10

に初期化された 10 個の要素のベクトルを本当に渡したい場合は"hello"f(vector(10, "hello"))単にf({10, "hello"}).

要約すると、引数が 1 つのコンストラクターは として宣言する必要がありますがexplicit、引数が 2 つの値の場合、これは必須ではないと思います。要素。

于 2013-02-02T18:06:27.470 に答える
1

「foo」を省略すると、コンパイルされず、文字列のベクトルを必要とする関数に int と文字列のペア (複合) 値を渡すと、それが期待されます。

いいえ、int と文字列のペアを渡すのではなく、"foo" のような文字列のコンテンツを含むサイズ 10 のベクトルを作成します。それには何も問題はありません!最初から等しい文字列を含むベクトルを作成すると便利な状況を理解できます。

于 2013-02-02T17:43:50.023 に答える
0

これは、文字列のベクトルを必要とする関数に int と文字列のペア (複合) 値を渡すときに期待することです。

さて、あなたの問題があります。

{...}「複合値」ではありません。リストではありません。「これらの値を使用してオブジェクトを初期化する」と書かれています。問題のオブジェクトが集合体の場合、集合体の初期化が使用されます。問題のオブジェクトが非集約型の場合、その型の一致するコンストラクターと C++11 の波括弧初期化リストのさまざまな規則に基づいて、呼び出すコンストラクターが選択されます。

{10, "foo"}2 つの値のリストと考えるべきではありません。これは、2 つの値を含む初期化子です。などと一緒に使用できますstd::pair<int, const char *>

std::vectorのコンストラクターが明示的でない理由は、まさにこの構成を許可するためです。単一引数のコンストラクターは明示的です。そうしないと、暗黙的な変換規則で次のことが可能になるからです。

std::vector<T> v = 5; //???

または、もっと重要なこと:

void Foo(const std::vector<T> &v);

Foo(5); //???

整数を暗黙のうちに s に変換できるようにしたくありませんstd::vector{}ただし、初期化子を使用している場合は、構文を確認できるため、より広い範囲の「暗黙的な」変換を許可する方が合理的です。

引数が 1 つの場合、ユーザーが何を意味するのかが明確ではありません。{} 構文を使用すると、ユーザーが意味すること、つまりオブジェクトを初期化することが明確になります。

Foo({10, "foo"}); //Initializes the first argument given the values.
于 2013-02-02T20:47:10.610 に答える