1

文字列の動的配列のコンテナ クラスを作成する割り当てに取り組んでいます。std::vector を使用すると、はるかに簡単/より適切に実行できることはわかっていますが、それは重要ではありません。コンストラクターで配列を初期化する正しい方法を見つけるのに問題があります。以下のように、変数 lineArray が使用されていないことをコンパイラからまだ警告されています。プログラムは、lineArray が使用されていないという警告とともにコンパイルされ、実行時にハングします。

MyBag::MyBag()
{
    nLines = 0;
    std::string lineArray = new std::string[0] ();
}
void MyBag::ResizeArray(int newLength)
{
    std::string *newArray = new std::string[newLength];
    //create new array with new length
    for (int nIndex=0; nIndex < nLines; nIndex++)
    {
        newArray[nIndex] = lineArray[nIndex];
        //copy the old array into the new array
    }
    delete[] lineArray; //delete the old array
    lineArray = newArray; //point the old array to the new array
    nLines = newLength; //set new array size
}
void MyBag::add(std::string line)
{
    ResizeArray(nLines+1); //add one to the array size
    lineArray[nLines] = line; //add the new line to the now extended array
    nLines++;
}

http://ideone.com/pxX18m

4

4 に答える 4

1

コンパイラによって報告される明らかなエラー (インスタンス変数に代入するのではなく、ローカル変数を初期化する) に加えて、より深刻な問題がnLinesありResizeArrayます。割り当てられた領域の終わり。次のようにコードを変更する必要があります。

void MyBag::ResizeArray(int newLength)
{
    // Add a trivial optimization:
    if (newLength == nLines) {
        // No need to resize - the desired size is already set
        return;
    }
    std::string *newArray = new std::string[newLength];
    //create new array with new length
    for (int nIndex=0; nIndex < nLines && nIndex < newLength ; nIndex++)
    {   //                             ^^^^^^^^^^^^^^^^^^^^^
        newArray[nIndex] = lineArray[nIndex];
        //copy the old array into the new array
    }
    delete[] lineArray; //delete the old array
    lineArray = newArray; //point the old array to the new array
    nLines = newLength; //set new array size
}
于 2013-05-10T17:16:04.500 に答える
1

救助への警告。コンパイラの警告があったのは良いことです。そうでなければ、これはバグであり、理解するのに時間がかかりました。

std::string lineArray = new std::string[0] ();
^^^^^^^^^^^

コンストラクターで呼び出される新しい変数を宣言しています。lineArrayクラスメンバーのものを使用していません。メンバーlineArrayポインターは、まだ初期化されていないメモリを指しています。


そのはず

lineArray = new std::string[0] ();
于 2013-05-10T17:12:01.270 に答える
1

lineArrayコンストラクターで呼び出されるローカル変数を使用しています。たとえば、次のようにデータ メンバーを使用します。

MyBag::MyBag()
{
    nLines = 0;
    lineArray = new std::string[0] ();
}
于 2013-05-10T17:12:10.897 に答える
1

シャドウ化されたメンバー変数と、ResizeArrayより小さな配列の問題に加えてadd()、6602 で示されているように、メソッドにバグがあります。 への呼び出し後ResizeArraynLinesは既に新しい値に更新されているため、実際には間違った配列の位置、そして間違ってnLines再びインクリメントします。必ず正しい位置に書き込んでください。インクリメントする必要はありません。

void MyBag::add(std::string line)
{
    int oldLength = nLines;
    ResizeArray(nLines+1); //add one to the array size
    lineArray[oldLength] = line; //add the new line to the now extended array
}
于 2013-05-10T17:31:12.043 に答える