2

私はlist<string> myList自分のクラスのプライベート属性としてを持っています。このリストの内容はコンパイル時に既知であり、一定です。その値を初期化するためのコンパクトな方法(C ++ 03)はありますか?私はこれだけを考えることができます:

MyClass::MyClass(){
myList.push_back(string("str1"));
myList.push_back(string("str2"));
myList.push_back(string("str3"));
etc.
}

私はこのようなものが欲しいです:

MyClass::MyClass():list("str1","str2","str3",etc.){
}
4

2 に答える 2

4

私はこのようなことをする傾向があります:

static const string my_strs[] =
{
  "str1",
  "str2",
  "str3"
};

static const num_my_strs = sizeof(my_strs)/sizeof(my_strs[0]);

list次に、 :を初期化するときが来ました。

MyClass::MyClass()
:  myList(my_strs, my_strs + num_my_strs)
{
}

...また:

MyClass::MyClass()
{
  copy( my_strs, my_strs+num_my_strs, back_inserter(myList));
}

このアプローチには賛否両論があります。明らかな欠点は、データのコピーが2つあることです。listこれはまた、コンパイル時に内容を知っていて、それらが決して変更されない場合、あなたはまったく必要でさえあるのかという疑問を提起します。なぜstatic constアレイを使用しないのですか?

プロ側では、リストを初期化するコードは1ライナーであり、リストに処理されているコンパイル時定数データを変更しても、変更する必要はありません。

編集:findプレーンな古いCスタイルの配列の ように標準ライブラリアルゴリズムを使用できます。例えば:

const string* it = std::find(my_strs, my_strs+num_my_strs, "str1");
if( it == (my_strs+num_my_strs) ) // functionally same as 'list.end()' eg, item not found
{ 
  // not found
}
else
{
  // found -- it points to item found
  string found_item = *it;
}

Edit2のような表現が明確に定義されているかどうかint a[2]; &a[2];が議論されています。上記のポインタ計算を編集して、UBを呼び出さないことがよく知られている方法を使用しました。

Edit3私はこれに関連する規格の関連する箇所を見つけました。上記の式(int a[2]; &a[2];)は、実際には未定義動作です。私はすでにその方法を使用しないように私の答えを編集しました。これを提起してくれた@MooingDuckに感謝します。

于 2012-11-07T17:32:44.433 に答える
3

このコードは完全にはテストされていませんが、C ++ 11で新しくてかっこいいものを使用できない場合は、これをお勧めします。

class MyClassCreator
{
    MyClass result;
public:
    MyClassCreator(std::string param)
    {
        result.myList.push_back(param);
    }

    MyClassCreator& operator()(std::string param)
    {
        result.myList.push_back(param); 
        return *this;
    }

    operator MyClass() { return result; }

};

使用法:

MyClass c = MyClassCreator("object1")("object2")("object3");

編集

http://ideone.com/LWGRCcで完全な例を参照してください

于 2012-11-07T17:30:49.040 に答える