1

問題を 2 つのオブジェクト (ポインター データ メンバーを含む) を単純な void 関数に渡すことに絞り込みました。関数は clean を返しますが、main() が終了しようとすると、2 つのオブジェクトの最初のものを再利用できません。以下は、問題を示すコードのサンプルです。オブジェクトが構築、渡され、破棄されるときに、オブジェクトのアドレスを表示する print ステートメントも一緒に示します。

「print1」のみを呼び出すと、プログラムは正常に実行されます。ただし、「printboth」を呼び出すと、オブジェクト「myNumbers」を解放できません。デストラクタ ステートメントを削除して、エラーを解消することもできます。

 delete [] number;

しかし、これは良い考えではないと思います。

誰にもアイデアはありますか?

class dummy
{
public:
    dummy() {
        number = new int[1];
        currentPos = -1;
        std::cout<<"default constructor called for "<<this<<std::endl;

    }
    dummy(int len) {
        number = new int[len];
        currentPos = -1;
        std::cout<<"parameterized constructor called for "<<this<<std::endl;

    }
    ~dummy() {
        cout<<"Calling destructor for "<<this<<endl;
        delete [] number;
    }
    int getNextNumber() {
        currentPos++;
        return number[currentPos];
    }
    void setNumbers(int position, int value) {
        number[position] = value;
    }
private:
    int* number;
    int currentPos;
};

void print1(dummy);
void printboth(dummy, dummy);

int main() {
dummy myNumbers(3);
myNumbers.setNumbers(0,0);
myNumbers.setNumbers(1,1);


dummy myOtherNumbers(3);
myOtherNumbers.setNumbers(0,4);
myOtherNumbers.setNumbers(1,5);

cout<<"Address of myNumbers is      "<<&myNumbers<<endl;
cout<<"Address of myOtherNumbers is "<<&myOtherNumbers<<endl;

print1(myNumbers);
printboth(myNumbers, myOtherNumbers);

system("PAUSE");
return 0;
}

void print1(dummy num) {
cout<<"Address of num is      "<<&num<<endl;
for (int i=0;i<4;i++)
    cout<<"Dummy number1 is "<<num.getNextNumber()<<endl;
return;
}
void printboth(dummy num1, dummy num2) {
cout<<"Address of num1 is      "<<&num1<<endl;
cout<<"Address of num2 is      "<<&num2<<endl;
for (int i=0;i<4;i++) {
    cout<<"Dummy number1 is "<<num1.getNextNumber()<<endl;
    cout<<"Dummy number2 is "<<num2.getNextNumber()<<endl;
    }
return;
}
4

1 に答える 1

2

あなたは3つのルールに従わなかった

問題は、print1 または printboth を呼び出すと、コンパイラがデフォルトのコピー コンストラクターを呼び出すことです (提供しなかったため)。そのコピー コンストラクターは、コピーの番号メンバー変数を元の値と同じ値に設定します。コピーに対してデストラクタが呼び出されると、メモリが解放されます。元のオブジェクトが既に解放されているメモリを指しているため、そのデストラクタが呼び出されるとクラッシュします(Nik Bougalis)。

void print1(dummy);
void printboth(dummy, dummy);

不必要なコピーを避けるために const 参照でダミーを渡すこともできますが、3 つのルールに従うことを強くお勧めします

void print1(const dummy& );
void printboth(const dummy&, const dummy&);

注:size =1まったく必要のない配列のみを作成しましint number;た。メンバーとして使用するだけです。number が動的に割り当てられた配列を保持している場合は、 を使用してみてくださいstd::vector<int>

getNextNumber には欠陥があり、複数回呼び出されると、number[currentPos];未定義の動作である番号外の境界にアクセスします。

int getNextNumber() {
        currentPos++;
        return number[currentPos];
    }

これは、示唆したことを意味します:

int getNextNumber() const {
      return number[currentPos];
   }
于 2013-01-22T01:21:43.683 に答える