C++では、常にnew
キーワードを使用してオブジェクトへのポインターを初期化していますか?
または、これもありますか?
MyClass *myclass;
myclass->DoSomething();
これはヒープではなくスタックに割り当てられたポインターだと思いましたが、オブジェクトは通常ヒープに割り当てられているので、私の理論はおそらく間違っていると思いますか?
ご意見をお聞かせください。
いいえ、割り当てられたオブジェクトをスタックするためのポインタを持つことができます:
MyClass *myclass;
MyClass c;
myclass = & c;
myclass->DoSomething();
これは、ポインターを関数パラメーターとして使用する場合はもちろん一般的です。
void f( MyClass * p ) {
p->DoSomething();
}
int main() {
MyClass c;
f( & c );
}
いずれにしても、ポインターは常に初期化する必要があります。あなたのコード:
MyClass *myclass;
myclass->DoSomething();
ndefined behaviourという恐ろしい状態につながります。
いいえ、できません、MyClass *myclass
は、ランダムなメモリ位置を指すポインター(ポインターのメモリーがスタックに割り当てられる)を定義します。このポインターを使用しようとすると、未定義の動作が発生します。
C++では、次のようにスタックまたはヒープにオブジェクトを作成できます。
MyClass myClass;
myClass.DoSomething();
上記はmyClassをスタックに割り当てます(この用語は標準ではないと思いますが、明確にするために使用しています)。 myClass
変数が範囲外になると、オブジェクトに割り当てられたメモリは自動的に解放されます。
メモリを割り当てる他の方法は、new
を実行することです。その場合、自分でdelete
を実行してメモリを解放する必要があります。
MyClass* p = new MyClass();
p->DoSomething();
delete p;
delete
部分を思い出してください。そうしないと、メモリリークが発生します。
メモリ管理に煩わされる必要がないため、可能な限りスタックに割り当てられたオブジェクトを使用することを常に好みます。
スタック上のオブジェクトが必要な場合は、これを試してください:
MyClass myclass;
myclass.DoSomething();
そのオブジェクトへのポインターが必要な場合:
MyClass* myclassptr = &myclass;
myclassptr->DoSomething();
まず、あなたのコード、
MyClass *myclass;
myclass->DoSomething();
未定義の動作 が発生します。ポインター「myclass」は「MyClass」タイプのオブジェクトを指していないためです。
ここで私はあなたのために3つの提案があります:
オプション1:-次のように、スタックでMyClassタイプのオブジェクトを単純に宣言して使用できます。
MyClass myclass; //allocates memory for the object "myclass", on the stack.
myclass.DoSomething();
オプション2:-new演算子を使用します。
MyClass *myclass = new MyClass();
ここで3つのことが起こります。
i)ヒープ上の「MyClass」タイプのオブジェクトにメモリを割り当てます。
ii)スタック上の「MyClass」タイプのポインター「myclass」にメモリを割り当てます。
iii)ポインタ「myclass」は、ヒープ上の「MyClass」型オブジェクトのメモリアドレスを指します。
これで、ポインターを使用して、「->」でポインターを逆参照した後、オブジェクトのメンバー関数にアクセスできます。
myclass->DoSomething();
ただし、ヒープから「MyClass」タイプのオブジェクトに割り当てられたメモリを解放してから、スコープに存在しないようにする必要があります。それ以外の場合は、 メモリリーク !
delete myclass; // free the memory pointed by the pointer "myclass"
オプション3:-以下のようにもできます。
MyClass myclass; // allocates memory for the "MyClass" type object on the stack.
MyClass *myclassPtr; // allocates memory for the "MyClass" type pointer on the stack.
myclassPtr = &myclass; // "myclassPtr" pointer points to the momory address of myclass object.
現在、ポインタとオブジェクトの両方がスタック上にあります。現在、スコープの外側に移動すると、ポインターとオブジェクトの割り当てられたメモリの両方が解放されるため、現在のスコープの外側にこのポインターを返すことはできません。
要約すると、オプション1と3はスタックにオブジェクトを割り当て、オプション2のみがヒープにオブジェクトを割り当てます。
メソッドにアクセスする場合:
1)クラスのオブジェクトを使用中:
Myclass myclass;
myclass.DoSomething();
2)クラスのオブジェクトへのポインターを使用している場合:
Myclass *myclass=&abc;
myclass->DoSomething();
クラス内でメソッドを静的として定義している場合、これは実際に可能です。
class myClass
{
public:
static void saySomething()
{
std::cout << "This is a static method!" << std::endl;
}
};
そしてメインから、ポインターを宣言し、静的メソッドを呼び出そうとします。
myClass * pmyClass;
pmyClass->saySomething();
/*
Output:
This is a static method!
*/
静的メソッドはクラスの特定のインスタンスに属しておらず、クラスのインスタンスの一部として割り当てられていないため、これは正常に機能します。
静的メソッドの詳細については、こちらをご覧ください。 http://en.wikipedia.org/wiki/Static_method#Static_methods
オブジェクトへのキャストポインタの簡単なソリューション
class myClass
{
public:
void sayHello () {
cout << "Hello";
}
};
int main ()
{
myClass* myPointer;
myClass myObject = myClass(* myPointer); // Cast pointer to object
myObject.sayHello();
return 0;
}