web-dev-qa-db-ja.com

C ++での静的ポインターの初期化

私はそのようなポインターである静的メンバーを持つクラスがあります:

animation.h

class Animation
{
public:
    Animation();
    static QString *m;

};

animation.cpp

#include "animation.h"

QString* Animation::m = 0;

Animation::Animation()
{
}

私はそのような別のクラスからその「m」ポインタを初期化しようとすると:

Animation::m = new QString("testing");

できます。

しかし、私がこれをこのようにすると:

QString x("Testing");
Animation::m = &x;

プログラムがクラッシュします。

この2番目の方法の何が問題になっていますか?

また、静的なゲッターとセッター関数を作成できるように、その静的ポインターをプライベートにしたいと考えています。 「x」がパラメーターに含まれるため、セッターは2番目のメソッドを使用する必要があるため、行き詰まります。

助けてくれてありがとう!

14
Yassir Ennazk

私はそれがその行でクラッシュしているのではないに違いないが、その後に。

問題は、自動メモリにある変数のアドレスを取得していて、後でその変数にアクセスしようとしていることです。変数xはスコープが終了すると破棄されますが、Animation::mはそのメモリを指します(xがスコープから外れた後に所有していないメモリ)。これは未定義の動作になります。

次のように違法になります:

int* x = NULL;
{
   int k = 3;
   x = &k;
}
*x = 4;

回避策ポインタではなく値に割り当てます(以前に有効なQString*に割り当てられていた場合):

QString x("Testing");
*(Animation::m) = x;
14
Luchian Grigore

この2番目の方法の何が問題になっていますか?

xが作成されたスコープを超えてアクセスする可能性が高いため、クラッシュします。

自動変数は、コントロールがスコープから出ると自動的に破棄されます{}それらが作成された場所なので、存在するデータの範囲を超えたポインタは、存在しないデータを指しています。このデータにアクセスすると、未定義の動作とクラッシュが発生します。

それについてどうやって行くのですか?

動的にメモリを割り当ててから、動的に割り当てられたポインタに文字列をコピーして、どこからでもアクセスできるようにする必要があります。このようにして、明示的にdeleteedしない限り、文字列は有効なままです。

2
Alok Save

xが(おそらく範囲外に)破壊された後でAnimation::mを使用すると、プログラムがクラッシュすることは間違いありません。

セッターを使用してAnimation::mに割り当てる場合は、引数をポインターとして、または参照によって渡す必要があります。

class Animation
{
public:
    Animation();

    void set_m( QString* ptr) {
        m = ptr;
    }

    void set_m( QString& ref) {
        m = &ref;
    }

private:
    static QString *m;

};

ただし、mを使用する場合は、mポイントがまだ有効であることを確認する必要があります。

1
Michael Burr