C++ と C++ セマンティクスの要点を見逃していると思います。C で行われている方法であるため、(ほとんど) すべてを値で渡すことで C++ が正しいという事実を見逃していました。しかし、以下に示すように、C だけではありません...
C のパラメーター セマンティクス
C では、すべてが値渡しされます。「プリミティブ」と「POD」は、値をコピーして渡されます。関数でそれらを変更しても、元のファイルは変更されません。それでも、一部の POD をコピーするコストは、取るに足らないものになる可能性があります。
ポインター表記 ( * ) を使用する場合、参照渡しではありません。アドレスのコピーを渡しています。これはほぼ同じですが、わずかな違いが 1 つあります。
typedef struct { int value ; } P ;
/* p is a pointer to P */
void doSomethingElse(P * p)
{
p->value = 32 ;
p = malloc(sizeof(P)) ; /* Don't bother with the leak */
p->value = 45 ;
}
void doSomething()
{
P * p = malloc(sizeof(P)) ;
p->value = 25 ;
doSomethingElse(p) ;
int i = p->value ;
/* Value of p ? 25 ? 32 ? 42 ? */
}
p->value の最終的な値は 32 です。p はアドレスの値をコピーして渡されたためです。したがって、元の p は変更されませんでした (そして、新しい p がリークされました)。
Java および C Sharp のパラメーター セマンティクス
驚く人もいるかもしれませんが、Java ではすべてが値によってもコピーされます。上記の C の例は、Java でもまったく同じ結果になります。これはほとんどあなたが望むものですが、C のように簡単に「参照/ポインターによって」プリミティブを渡すことはできません。
C# では、"ref" キーワードが追加されました。これは、C++ のリファレンスとほぼ同じように機能します。ポイントは、C# では、関数宣言とすべての呼び出しの両方で言及する必要があるということです。繰り返しますが、これはあなたが望むものではないと思います。
C++ のパラメーター セマンティクス
C++ では、ほとんどすべてが値をコピーして渡されます。シンボルの型だけを使用しているときは、シンボルをコピーしています (C で行われているように)。これが、* を使用しているときに、シンボルのアドレスのコピーを渡す理由です。
しかし、& を使用している場合は、実際のオブジェクト (構造体、int、ポインターなど) を渡していると仮定します。参照。
これをシンタックス シュガーと間違えがちです (つまり、舞台裏ではポインターのように機能し、生成されたコードはポインターと同じように使用されます)。しかし...
真実は、参照が構文糖衣以上のものであるということです。
- ポインターとは異なり、スタック上にあるかのようにオブジェクトを操作できます。
- const キーワードに関連付けられている場合、unline ポインターは、(主にコンストラクターを介して) ある型から別の型への暗黙的な昇格を許可します。
- ポインターとは異なり、シンボルは NULL/無効であることは想定されていません。
- 「by-copy」とは異なり、オブジェクトのコピーに無駄な時間を費やすことはありません
- 「by-copy」とは異なり、[out]パラメータとして使用できます
- 「by-copy」とは異なり、C++ では OOP の全範囲を使用できます (つまり、インターフェイスを待っている関数に完全なオブジェクトを渡します)。
したがって、参照には両方の長所があります。
C の例を見てみましょう。ただし、doSomethingElse 関数に C++ のバリエーションがあります。
struct P { int value ; } ;
// p is a reference to a pointer to P
void doSomethingElse(P * & p)
{
p->value = 32 ;
p = (P *) malloc(sizeof(P)) ; // Don't bother with the leak
p->value = 45 ;
}
void doSomething()
{
P * p = (P *) malloc(sizeof(P)) ;
p->value = 25 ;
doSomethingElse(p) ;
int i = p->value ;
// Value of p ? 25 ? 32 ? 42 ?
}
結果は 42 で、古い p がリークされ、新しい p に置き換えられました。C コードとは異なり、ポインターのコピーを渡すのではなく、ポインターへの参照、つまりポインター自体を渡すためです。
C++ を使用する場合、上記の例は非常に明確である必要があります。そうでない場合は、何かが欠けています。
結論
C++ は、C、C#、または Java (JavaScript でさえ... :-p ...) であれ、すべてが機能する方法であるため、コピー/値渡しです。また、C# と同様に、C++ にはおまけとして参照演算子/キーワードがあります。
さて、私が理解している限りでは、あなたはおそらく私が冗談めかしてC+と呼んでいるもの、つまり C++ のいくつかの機能が制限された C を行っているのでしょう。
おそらく、あなたのソリューションは typedef を使用しています (ただし、役に立たない typedef によってコードが汚染されているのを見て、C++ の同僚を激怒させるでしょう...)。
別の投稿で述べたように、C 開発 (何でも) から C++ 開発に考え方を変えるか、おそらく別の言語に移行する必要があります。ただし、C++ の機能を使用して C の方法でプログラミングを続けないでください。使用するイディオムの力を意識的に無視/難読化すると、最適ではないコードが生成されます。
注: また、プリミティブ以外のものをコピーして渡さないでください。関数を OO 容量からキャストしますが、C++ では、これは望んでいるものではありません。
編集
質問は多少変更されました ( https://stackoverflow.com/revisions/146271/listを参照)。元の回答をそのままにして、以下の新しい質問に回答します。
C++ のデフォルトの参照渡しセマンティクスについてどう思いますか? あなたが言ったように、それは互換性を壊し、プリミティブ(つまり、コピーによって渡される組み込み型)と構造体/オブジェクト(参照として渡される)に対して異なるパスバイを持つことになります。「値渡し」を意味する別の演算子を追加する必要があります(extern「C」は非常にひどいもので、すでにまったく別の何かに使用されています)。いいえ、今日の C++ での方法がとても気に入っています。
[...]参照演算子は、変数アドレスを取得する方法のように思えます。これは、ポインターを取得するために使用した方法です。つまり、同じ演算子ですが、異なるコンテキストでは異なる意味を持つということは、あなたにとっても少し間違っていると感じませんか? はいといいえ。演算子 >> は、C++ ストリームで使用される場合にもセマンティクスを変更しました。次に、演算子 += を使用して strcat を置き換えることができます。演算子 & が使用されたのは、その意味が「ポインターの反対」であるためであり、さらに別の記号を使用したくなかったためだと思います (ASCII は制限されており、スコープ演算子 :: とポインター -> は、他の記号がほとんどないことを示しています使用可能です)。しかし今、もし & が気になるなら && は本当にあなたを不安にさせるでしょう、彼らは C++0x に単項 && を追加したからです (一種のスーパーリファレンス...)。自分で消化するのはまだ先ですが…