私はそのようなポインターである静的メンバーを持つクラスがあります:
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番目のメソッドを使用する必要があるため、行き詰まります。
助けてくれてありがとう!
私はそれがその行でクラッシュしているのではないに違いないが、その後に。
問題は、自動メモリにある変数のアドレスを取得していて、後でその変数にアクセスしようとしていることです。変数x
はスコープが終了すると破棄されますが、Animation::m
はそのメモリを指します(x
がスコープから外れた後に所有していないメモリ)。これは未定義の動作になります。
次のように違法になります:
int* x = NULL;
{
int k = 3;
x = &k;
}
*x = 4;
回避策ポインタではなく値に割り当てます(以前に有効なQString*
に割り当てられていた場合):
QString x("Testing");
*(Animation::m) = x;
この2番目の方法の何が問題になっていますか?
x
が作成されたスコープを超えてアクセスする可能性が高いため、クラッシュします。
自動変数は、コントロールがスコープから出ると自動的に破棄されます{
}
それらが作成された場所なので、存在するデータの範囲を超えたポインタは、存在しないデータを指しています。このデータにアクセスすると、未定義の動作とクラッシュが発生します。
それについてどうやって行くのですか?
動的にメモリを割り当ててから、動的に割り当てられたポインタに文字列をコピーして、どこからでもアクセスできるようにする必要があります。このようにして、明示的にdelete
edしない限り、文字列は有効なままです。
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
ポイントがまだ有効であることを確認する必要があります。