2016-09-04 17 views
-2

私はsomereasonのために私はそれをしたい前に、私のオブジェクトのD'のTORが呼び出されると、それは私のコードをクラッシュさせ、イマイチの作業を演算子オーバーロードで自分のint型配列のクラスが、気にいらをinitiallizeしようとした:なぜ、それはしてはいけないのですか?

#include "stdafx.h" 
#include "Array.h" 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Array arr(6); 
    arr[3] = 6; //code crashes here 
    printf("%d\n", arr[0]); 
    return 0; 
} 

と今クラス: ヘッダファイル:

#pragma once 
#include <malloc.h> 
class Array 
{ 
public: 
//ctor dtor and operator overloading 
    Array(int); 
    Array(int *, int); 
    ~Array(); 
    Array operator[](int i); 
//here memebers are defined 
    int *arr; 
    int size; 
}; 

---- CPPファイル---

#include "stdafx.h" 
#include "Array.h" 

//the function mallocs size for the array. 

Array::Array(int g = 1) :size(g) //diplomatic value for size =1 
{ 
    this->arr = (int*)malloc(sizeof(int) * this->size); 

} 
Array::Array(int *p, int m_size=1) :arr(p), size(m_size) 
{} 

Array::~Array() 
{ 
    delete arr; 
} 

この機能の後に私のOBJ operator[]関数値によってArrayオブジェクトを返すので、ECTは

Array Array::operator[] (int i){ 
    for (int j=0; j < i; ++j) 
    { 
     ++(this->arr); 
    } 
    return *this; 
} 
+2

なしまったく意味をなさないについて読むことをお勧めしたいです。しかし、あなたの大きな問題は、3つのルールに正しく従わないことです。 –

+0

私はそのコードをコンパイルすると信じられません –

+4

実際には、このコードは素晴らしいです。意図した目的ではなく、例として挙げられます。このコードは、奇跡的な理由からうまく構成されているようですが、ほとんどの部分は、一般的なイディオムや期待とはまったく異なるものです。 –

答えて

2

TOR D'によって削除されています。それはあなたが行うときに代入arr[3] = 6オペレータは、thisのコピーを返します(それが一致するコンストラクタを持っているので)、コンパイラはその後、暗黙的に整数6から配列オブジェクトを作成し、突然、あなたの割当が

どこか
arr[3] = Array(6); 

のように見えること一時配列オブジェクト(operator[]関数によって返されたものと、コンパイラが割り当ての右側に作成したもの)を破壊する必要がありますが、それまでにはすべて同じポインタarrを使用する複数のオブジェクトがあります。最初の一時オブジェクトは破棄され、ポインタを削除し、他のすべてのオブジェクトは無効なポインタで残します。次に、次の一時オブジェクトが破棄され、今無効なポインタを削除しようとします。ブーム、あなたはクラッシュしている。

問題を解決するには、2つのことが必要です。最初はoperator[]関数が間違った型を返し、それが代わりに含まれる配列の要素への参照を返す必要があることを実現することである。

int& Array::operator[](size_t const i) 
{ 
    return arr[i]; 
} 

あなたがする必要がある第二のものはおよそthe rules of three, five and zeroを読むことです。 int値からオブジェクトを構築し、あなたがexplicitとしてコンストラクタをマークする必要があります誤ってから、コンパイラを防ぐためにも

、:

explicit Array(int); 
0

主な問題

関係なく、あなたの他の問題のコードのoperator[]の署名が間違っています:

Array Array::operator[] (int i){ 
    ... 
} 

ここで配列の要素を返さないでください!代わりに完全に新しい配列を返します。したがって、あなたの間違ったステートメントでは、新しい一時配列が構築され、囲み式の終わりに破棄されます。

代わりにこれを試してください。少なくとも、それはすぐにクラッシュしなくなります。

int& Array::operator[] (int i){ 
    return arr[i]; 
} 

をクラッシュ残念ながら

の原因、あなたはmalloc()を使用してARR割り当てます。決してこれをC++で行うのではなく、代わりにnew[]を使用してください。これは、それ自体でクラッシュにつながることはありません。しかし、あなたのデストラクタに加えて、deleteを使用します。

それは(一時的Arrayが破壊されてしまったとき、これは、あなたの元のコードでクラッシュする)任意の他の組み合わせは、未定義の動作ですmalloc()/free()またはnew/deleteまたはnew[]/delete[]のいずれかです。次のように

は、問題を修正:

Array::Array(int g = 1) :size(g) //diplomatic value for size =1 
{ 
    arr = new int[size]; 
} 
Array::~Array() 
{ 
    delete[] arr; 
} 

これは、コンパイルして動作します:online demo

その他の深刻な問題

最後に物事をさらに悪化させるために、あなたのオリジナルのインデックスオペレータが戻ります、既存のクローンを作成するArray。これは今解決されました。しかし、あなたがあなたの配列のコピーを作るなら、別の問題があるでしょう:

これはarrポインターを2か所で使うことになります。破棄された最初のArrayは、元のArrayで使用されているarrポインタを無効にします。その後のarrの逆参照は、未定義の動作になります。

それは私のオンラインデモで解決していないので、私は、私は強く、このコードのrule of 3

関連する問題