2012-03-08 1 views
1

に比べて、私は次のように定義され、intWrapperという名前のint型へのラッパークラス、および2つの数値を加える機能addNを持っている:メイン(で、のVisual Cで異なる動作++ MinGWの

intWrapper* addN(intWrapper *first, intWrapper *second) 
{ 
    intWrapper c; 
    c.setData(first->getData() + second->getData()); 
    return &c; 
} 

を次に私はこれを行う)機能:のDev-C++(MINGW32)で

intWrapper first(20), second(40); 
intWrapper* t = addN(&first, &second); 
cout << (*t).getData() << endl; 

これは意図したとおりに実行し、その値60を印刷しますが、ビジュアルC++で私は値-858993460を取得します。
しかし、新しいキーワードを使用してaddN関数内に新しいオブジェクトを作成すると、Visual C++でも60が出力されます。私はなぜこれが起こるのか興味をそそられています。何かご意見は?
完全なコードはここにある:

#include <iostream> 
using namespace std; 

template<typename T, T defaultValue> 
class Wrapper 
{ 
     private: T n_; 
     public: 
      Wrapper(T n = defaultValue) : n_(n) {} 
      T getData() 
      { 
        return n_; 
      } 
      void setData(T n) 
      { 
        n_ = n; 
      } 
}; 

typedef Wrapper<int, 47> intWrapper; 

intWrapper* addN(intWrapper *first, intWrapper *second) 
{ 
    intWrapper c; 
    c.setData(first->getData() + second->getData()); 
    return &c; 
} 

int main() 
{ 
    intWrapper p; 
    cout << p.getData() << endl; 
    intWrapper first(20), second(40); 
    intWrapper* t = addN(&first, &second); 
    cout << (*t).getData() << endl; 
    system("PAUSE"); 
    return 1; 
} 
+0

また、VC++では、「bad memory」のすべての部分に0xbaadf00d、0xcccccccc、0xffffffffなどの値を入力するのが好きです。あなたの場合は、0xFFFFFFFFCCCCCCCCという値があります。これは、プログラムが何らかの嘔吐を飲み込んだようです。 – ActiveTrayPrntrTagDataStrDrvr

+0

あなたは高い警告レベルを有効にするのに慣れるべきです... – PlasmaHH

答えて

7

これは未定義の動作です:あなたは、関数が戻り値はダングリングポインタであることを意味返したときに破壊されるローカル変数へのポインタを返すされています。

未定義の動作は、何らかの事態が発生する可能性があることを意味します。クラッシュする可能性があります。正しく動作しているように見えたり、正常に動作しない可能性があります。

newを使用すると、intWrapperインスタンスは関数の範囲外に存在し、未定義の動作ではなく、正しく動作します(VCとMingW32の両方)。必要がなくなった場合はdeleteを返信してintWrapper*を覚えておいてください。 Dev-C++(MINGW32)において

+0

ああ、私は、それはかなり明らかで、本当に愚かです。ありがとうございました。 – hero47

+2

@ hero47この回答があなたの問題に対する(または最良の)解決策だったら、[それを受け入れる](http://meta.stackexchange.com/q/5234/162011)が正しい回答になります。 –

0

を意図したように、これは意図した通りに実行されない実行します。 プログラムは未定義の動作を使用します。あなたがそれをするときに何かが起こる可能性があります。

ローカル変数へのポインタを返します。関数から戻ると、ローカル変数は存在しなくなります。つまり、以前にその変数で使用されていたメモリには、のいずれかが含まれている可能性があります。つまり、読み取り不能になっている可能性があります(つまり、segfault/access violationが発生します)。あなたがロシアのルーレットを好きで、あなたのプログラムで完全に予測できない振る舞いをしたいのでない限り、あなたはそうしてはいけません。

どちらの値によってIntWrapper返す(あなたはそのためのコンストラクタと代入演算子をコピーする必要があります):

intWrapper addN(intWrapper *first, intWrapper *second) 
{ 
    intWrapper c; 
    c.setData(first->getData() + second->getData()); 
    return c; 
} 

、またはnewでそれを配分して、結果を返す(そして後でそれを削除するのを忘れ)

intWrapper* addN(intWrapper *first, intWrapper *second) 
{ 
    intWrapper *c = new intWrapper; 
    c->setData(first->getData() + second->getData()); 
    return c; 
} 

スマートポインタ(shared_ptr)を使用して自動的に削除します。

関連する問題