私は C++ を学んでおり、最近はツリーについて読んで学んでいます。ポインターを使用する利点は何ですか?
たとえば、Node クラスがあり、Function という関数がある場合、次の違いは何ですか。
Function (Node *node)
Function (Node node)
1つはポインタをパラメータとして取り、もう1つはそうではないことを私は知っています。しかし、私はその違いが何であるかを完全には理解していません。
Function(Node node)
引数のコピーを作成します。特に、関数は元の引数を変更することはできないため、Function で node を操作しても、Function(node) を呼び出したコードにはそれらの変更が表示されません。
他の人があなたのデータを台無しにできないように、それが必要な場合もあります。
大きなオブジェクトの場合、データのコピーに必要な時間は、ポインターを使用しないことの欠点でもあります。
関数定義の内容を変更することができFunction (Node *node)
ます。node
関数定義の内容を変更することはFunction (Node node)
できません。node
まず、オブジェクトとは何かを理解する必要があります。
House home;
これにより、スタック上にクラス「House」のインスタンス用のストレージが作成され、コンストラクターが呼び出され、「home」という名前が指定されて後で参照されます。
オブジェクトはスタック上のスペースを占有しますが、スタックは、スタックとして使用するように指定された単なるメモリ領域です。「セントラル ドライブ」と同じ名前が付けられたのは、建設されたときに町の中心を走っていたからです。今日では、道路を区別する方法になっています。
値渡しについて話すとき、たとえば
int SendGift(House h, Gift g)
これは、この関数を呼び出すと、関数が操作するために呼び出した House の新しいローカル コピーを作成することを意味します。
void SendGift(House h, Gift g)
{
h.porch.insert(g);
g.setLocation(h);
}
"House h" と "Gift g" はどちらも関数 SendGift の一時的なローカル変数なので、次のように呼び出すと:
House home;
Gift gift(Gift::Dollars, 1 * 1000 * 1000);
SendGift(home, gift);
変数「ホーム」は、ギフトと同様に変更されません。私たちが行った変更はすべて「g」と「h」であり、関数が終了すると消えました。
コードは、「100 万ドルの贈り物をして、それを 123 Beech Street の住宅に届ける」ということを意図していました。しかし、私たちは値で渡したので、実際には「100万ドルの贈り物をしてください。家と贈り物のコピーを作成し、コピーをコピーハウスに入れ、両方を破壊してください」と書かれていました。
また、「House」オブジェクトが数キロバイトの大きさの場合、値を渡すたびに大量のデータを一時オブジェクトにコピーする必要があり、非常にコストがかかる可能性があります。
整数などの小さなオブジェクトでは、これは No Big Deal(TM) です。しかし、家のような大きなオブジェクトの場合、これはコストがかかりすぎます。
そのため、代わりにポインターで渡したい場合があります。
int SendGift(House* h, Gift* g)
{
h->porch.insert(g);
g->setLocation(h);
}
ポインタは、オブジェクトのインスタンスのメモリ内の場所であるアドレスを含む変数です。そのため、家をレンガごとに SendGift のテンポラリーにコピーする代わりに、アドレスを渡しました。だから今私たちの呼び出し
したがって、ポインター (または参照) で渡す主な理由は 2 つあります。
通常、インテントが #1 ではなく #2 の場合、パラメーターを const としてマークする必要があります。
#include <iostream>
struct BigObj
{
BigObj() : m_useCount(0) {}
int m_useCount;
int m_stuff[4096];
};
void BigObjByValue(BigObj b)
{
b.m_useCount++;
std::cout << "BigObjByValue " << (&b) << ". m_useCount is now " << b.m_useCount << std::endl;
}
void BigObjByPtr(BigObj* b)
{
b->m_useCount++;
std::cout << "BigObjByValue " << (b) << ". m_useCount is now " << b->m_useCount << std::endl;
}
void BigObjByConstPtr(const BigObj* b)
{
//b->m_useCount++; // compiler won't allow this, try uncommenting.
std::cout << "BigObjByValue " << (b) << ". m_useCount is now " << b->m_useCount << std::endl;
}
int main()
{
BigObj mainB;
std::cout << "Created mainB at " << (&mainB) << " useCount = " << mainB.m_useCount << std::endl;
BigObjByValue(mainB);
std::cout << "in main, m_useCount = " << mainB.m_useCount << std::endl;
BigObjByPtr(&mainB);
std::cout << "in main, m_useCount = " << mainB.m_useCount << std::endl;
BigObjByConstPtr(&mainB);
std::cout << "in main, m_useCount = " << mainB.m_useCount << std::endl;
return 0;
}
ideone ライブ デモ: http://ideone.com/SjkoNq