structオブジェクトをパラメーターとしてc ++の関数に渡すことをお勧めしますか?
質問
以下でライブで例を試しました。
typedef struct point
{
int x;
int y;
} point;
void cp(point p)
{
cout<<p.x<<endl;
cout<<p.y<<endl;
}
int main()
{
point p1;
p1.x=1;
p1.y=2;
cp(p1);
}
印刷された結果は次のとおりです。
1
2
これが私が期待したことです。私の質問は、パラメーターPはオブジェクトP1の完全なコピーを取得しますか?もしそうなら、私はこれが良い習慣なのだろうか? (構造体のサイズが大きくなったとき、これにより多くのコピーオーバーヘッドが作成されると思いました)。
解決
構造体をパラメーターとして渡すことには何の問題もありません。すべてがC ++で値で渡されるため、完全なコピーが実際に作成されます。
あなたがあなたの例で与えた構造体は小さいので、あなたがそれを価値で渡す場合、それはおそらく問題ではないでしょう。ただし、より大きなデータ構造を使用している場合は、参照して渡すことをお勧めします。
ただし、参照を通過すると、関数内の構造体を変更すると、元の構造体が変更されることを意味します。構造体を変更しないすべての場合にconstキーワードを使用してください。これにより、関数が情報を変更するかどうかについての即時の情報が得られます。
あなたの例は、この方法で参照を使用するように変更できます。
typedef struct point
{
int x;
int y;
} point;
void cp(const point& p) // You can know that cp doesn't modify your struct
{
cout<<p.x<<endl;
cout<<p.y<<endl;
}
void mod_point(point& p) // You can know that mod_points modifies your struct
{
p.x += 1;
p.y += 1;
}
int main()
{
point p1;
p1.x=1;
p1.y=2;
cp(p1);
mod_point(p1);
cp(p1); // will output 2 and 3
}
他のヒント
はい、これには何の問題もありません。 p
の完全なコピーです p1
. 。私は電話しません struct
2つで int
大きいですが、 struct
大きくなり、関数本文でそれを変更する必要がない場合は、const参照で渡すことを検討できます。
void cp(const point& p)
{
// ...
}
私があなたの質問に答えを与える前に (この投稿の最後にそれを見つけます)、ここにあなたが関数に引数を渡すための可能性の簡単な要約を示します:
1.コピー構築されたオブジェクト(バリューパス):
void cp(point p);
これは価値があります。一時的な point
オブジェクトは作成され、何からでもコピー構築されます point
あなたが渡すオブジェクト cp
. 。実行が離れたら cp
機能、一時的なオブジェクトが破壊されます。
関数は関数に渡されたもののコピーで動作するため、そのローカルを変更できることに注意してください point
オブジェクトが好きなだけ、発信者の元のオブジェクトは影響を受けません。この動作をパスごとのパラメーターで変更する方法はありません。
2.オブジェクトへの参照(パスバイ参照):
void cp(point& p);
これはパスバイレファレンスです。関数に渡された実際のオブジェクトは、関数内で利用可能です(および潜在的に変更される可能性があります)。関数がパスインオブジェクトを変更できるようにしたくない場合は、パラメーターを次のように宣言します const point&
:
void cp(const point& p);
3.オブジェクトへのポインター(パスバイ参照):
void cp(point* p);
これはまた、いくつかの微妙な違いをもたらすパスバイバイエレンスです。顕著な違いの1つは、関数にヌルポインターを渡すことができることです。参照のため、これは参照では不可能です しなければならない 初期化され、その後再現できません。 - 参照と同様に、あなたが禁止したい場合 cp
パスインの変更から point
, 、それをconstとして宣言します:
void cp(const point* p);
あなたの質問への答え:
価値のあるパラメーターは、本質的に悪くはありません。もちろん、コピー構造が高価な(非常に大きなオブジェクトまたは複雑なオブジェクトなど)、または特定の副作用があるタイプがあります(例: std::auto_ptr
)。これらの場合、注意する必要があります。それ以外の場合、それは完全に合理的な用途を持つC ++の別の機能です。
void cp(point p){
}
価値でそれを取得します
void cp(point *p){
}
参照によって取得します
他のデータ変数と同様に。
Javaでは、シナリオは異なります。通過するオブジェクトは常に参照してください。
あなたの場合、ポイント構造は「値によって」渡され、構造全体がコピーされることを意味します。ビッグデータ型の場合、これは実際に遅くなる可能性があります。
参照によってオブジェクトを渡すことを検討できます
void cp(point& p) // p may be altered!
または、const Referenceになります
void cp(const point& p) // p may not be altered!
価値でオブジェクトを渡すことを避ける可能性をご覧ください。オブジェクトは「コピーされた」だけでなく、コピー構築されています。したがって、これには、オブジェクトがより多くのオブジェクトを構成または導出されている場合、コピーコンストラクターとコピーコンストラクターのチェーンを呼び出すことが含まれます。可能であれば参照で合格します。
void cp(point&p const)const {
cout << p.x << endl;
cout << p.y << endl;
}