2011-10-19 17 views

答えて

3

あなたは値によって参照を渡すのではなく、あなたが関数呼び出しでコピーを作成する必要があることを意味した値によってオブジェクトを渡していることを、よく、参照によってオブジェクトを渡します。関数は、渡されたオブジェクトを変更したりしません

  1. しかし、パッシング・バイ・参照することはあなたが知っておく必要があります質問の新しいセットを導入して?そうでない場合は、const修飾子を入れてください

  2. 関数はオブジェクトを変更する必要がありますが、変更を関数境界外に公開する必要はありませんか?その場合、本当に欲しいのはコピーです。
  3. この関数は、渡されたオブジェクトの参照をどこかに保存しますか?その場合、オブジェクトの所有権がどのように渡され、削除するのが安全なのかを理解する必要があります。パッシング・バイ・参照すると、関数呼び出し安く作るという理由だけであなたはどのような場合には、それを使用しなければならないことを意味しません:あなたは、これらの問題

点であるに対処するsmart pointersを使用することができます。

+0

ケース2では、私はまだパラメータとして 'const&'を置いて、関数の内部にコピーを作成します。特に、コピーを行う前に関数が失敗/復帰する可能性を考慮してください。 – xanatos

+0

@xanatosはい、可能ですが、この関数が頻繁に呼び出され、コピーを実行する前に戻る可能性が高い場合、引数を値渡しする方が簡単です。 – akappa

+0

(私はBjörnPollexの答えにSteve Jessopの議論がこの論争の中で良いと思っています) – akappa

0

一般的に、パフォーマンスに関する限り、参照渡しは値渡しよりも優れています(組み込みデータ型は除外します)。だからはいfunc(string&)func(string)より優れています。関数が終了すると、渡されたを変更することができます。 stringを変更しない場合は、func(const string&)を使用してください。

さらに、STLではstringが最適化されていることを覚えています。値によってstringを渡すと、必ずしもヒープに新しい文字列が作成されるとは限りません。値渡しは、あなたが期待するほど高価ではないかもしれません。例えば

string s1 = "hello"; // new buffer allocated on heap and copied "hello" 
string s2 = s1; // s2 and s1 both 'may' refer to same heap 
... 
s1 += " world"; // s2 continue referring to old heap ... 
       // new heap created to accomodate "hello world" referred by s1 
+1

'string'最適化の問題について少し詳しく説明します:' strings'は[COW](http://en.wikipedia.org/wiki/Copy-on-write) 'dです。 'string'を値で渡すと、新しい' string'が作成されますが、元の 'string'と新しい' string'の間で基礎となるデータ(例えば文字配列)が共有されます。したがって、ローカルコピーが変更されない限り、オーバーヘッドはありますが、それほど多くはありません。 **編集:**私は私のコメントを書いている間にこれを説明するために編集したように見えます。 – Mac

+1

@Macこれは必ずしも真実ではなく、実装によってはCOWがあり、そうでないものもあれば、C++ 11のいくつかの変更がCOW文字列で準拠した標準ライブラリを提供することを不可能にしたと私は考えています。この最後の部分がわからない。 –

+0

@DavidRodríguez-dribeas:絶対に正しい - 私が言っていることは 'string'sは*典型的な* COWだと言った。 – Mac

3

func(string &)は参照によって文字列を渡します。これは、コピーされず、関数がそれを変更できることを意味します。

func(string)は値で文字列を渡します。つまり、コピーが作成され、その関数はその文字列のローカルコピーのみを変更できます。

コピーせずに文字列を渡しますが、変更されないようにするには、func(const string&)を使用してください。

あなたの関数が引数のコピーをとる必要がある場合は、値渡しが望ましいです。参照を渡す

+0

さらに、 'func'がそのパラメータを変更する必要がない場合は' func(const string&) 'を考慮する必要があります。とにかく 'func(string)'を持っていると考えると、関数はこのパラメータを変更できないので、 'func(const string&)'を使う必要があります。... – MichalR

+0

「関数が引数のコピーをとる必要がある場合、値渡しが望ましい。どのように役立つだろうか? –

+0

@Paul:それは引数とスクリプトのために別々の変数を必要としないので、関数をやや簡単にし、エラーを起こしにくくなります。 –

2

は、通常、複雑な型のため、より効率的になりますが、あなたは関数がそれを変更できるようにしたい場合を除き、それはconstへの参照する必要があります:

void f(string);  // function gets its own copy - copying may be expensive 
void f(string&);  // function can modify the caller's string 
void f(string const&); // function can read the caller's string, but not modify it 
1

ます。またfunc(const string&)の代わりに使用することができますfunc(string&)を使用して、渡された参照パラメータが関数内で誤って変更されていないことを確認します。

0

はい。参照を渡すことは常に効率的です。
文字列は値によって格納され、コピーにはO(n)の長さがかかることがあります(コピーには文字列の長さに比例した時間がかかります)。また、通常はコピーよりもはるかに高価なヒープメモリが割り当てられます。
unintenionalな変更を避けるために、reference-to-const、つまりfunc(const string &)を渡すことも考えられます。

1

stringとして渡すと、文字列が最初にコピーされ、コピーが関数に送信されます。文字列などの高価なオブジェクトを渡す最善の方法は、関数で修正する必要がない場合はconst string&です。

constが重要です。まず、関数内で文字列が変更されないようにします。また、func("this is a litearal because it isn't inside a variable")を使用せずにリテラルを関数に渡すことはできません。

0

また、移動セマンティクスを使用してrvalue参照最適化を使用することもできます。

void func(string &&s) 
{ 
    myS = std::move(s); 
} 
関連する問題