web-dev-qa-db-ja.com

[]を使用するときにC ++マップタイプ引数に空のコンストラクターが必要なのはなぜですか?

C++標準リストおよびデフォルトで構築可能なタイプ も参照してください

重大な問題ではなく、特定の引数なしでクラスをインスタンス化したくないので迷惑です。

#include <map>

struct MyClass
{
    MyClass(int t);
};

int main() {
    std::map<int, MyClass> myMap;
    myMap[14] = MyClass(42);
}

これにより、次のg ++​​エラーが発生します。

/usr/include/c++/4.3/bits/stl_map.h:419:エラー:「MyClass()」の呼び出しに一致する関数がありません

デフォルトのコンストラクターを追加すると、これは問題なくコンパイルされます。構文の誤りが原因ではないことは確かです。

85
Nick Bolton

この問題にはoperator []が伴います。 SGIドキュメントからの引用:

data_type& operator[](const key_type& k)-特定のキーに関連付けられているオブジェクトへの参照を返します。マップにそのようなオブジェクトがまだ含まれていない場合、_operator[]_はデフォルトのオブジェクトdata_type()を挿入します。

デフォルトのコンストラクターがない場合は、挿入/検索関数を使用できます。次の例は正常に機能します。

_myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
_
146
bayda

はい。 STLコンテナの値は、コピーセマンティクスを維持する必要があります。 IOW、それらはプリミティブ型(例:int)のように振る舞う必要があります。これは、とりわけ、デフォルトで構築可能であることを意味します。

これ(およびその他の要件)がなければ、STLコンテナが実装されているデータ構造にさまざまな内部コピー/移動/スワップ/比較操作を実装することは不必要に困難です。

C++標準を参照すると、答えが正確ではなかったことがわかります。 デフォルトの構築は、実際には要件ではありません

20.1.4.1以降:

デフォルトのコンストラクターは不要です。特定のコンテナクラスメンバ関数シグネチャは、デフォルトのコンストラクタをデフォルトの引数として指定します。 T()は明確に定義された式でなければなりません...

したがって、厳密に言えば、値の型は、デフォルトのコンストラクタをシグネチャで使用するコンテナの関数を使用している場合にのみ、デフォルトで構築可能である必要があります。

STLコンテナに保存されているすべての値からの実際の要件(23.1.3)は、CopyConstructibleおよびAssignableです。

Comparable(マップ内のキーなど)など、特定のコンテナーには他の特定の要件もあります。


ちなみに、次のコードは comea でエラーなしでコンパイルされます。

#include <map>

class MyClass
{
public:
    MyClass(int t);
};

int main()
{
    std::map<int, MyClass> myMap;
}

したがって、これはg ++の問題である可能性があります。

6
Assaf Lavie

Stl :: mapの保管タイプの要件を確認してください。多くのstlコレクションでは、格納された型に特定のプロパティ(デフォルトコンストラクター、コピーコンストラクターなど)が含まれている必要があります。

引数なしのコンストラクターは、演算子[]がキーで呼び出されたときに使用されるため、stl :: mapで必要になりますが、キーはまだマップに保持されていません。この場合、operator []は、パラメーターなしのコンストラクターを使用して構築された新しいキーと値で構成される新しいエントリを挿入します。そして、この新しい値が返されます。

2
oo_olo_oo