6

C++11 について根本的な誤解があるに違いありません。私の教授は、参照またはポインター以外では、非プリミティブ型を関数に渡すことはできないと言いました。ただし、次のコードは問題なく動作します

#include <iostream>
using namespace std;

class MyClass
{
public: 
    int field1;
};

void print_string(string s) { 
    cout << s << endl; 
}

void print_myclass(MyClass c) { 
    cout << c.field1 << endl; 
}

int main(int argc, char *argv[]) 
{
    string mystr("this is my string"); 
    print_string(mystr); // works
    MyClass m; 
    m.field1=9; 
    print_myclass(m); 
    return 0;
}

プログラムを実行すると、次の出力が得られます

this is my string
9

RUN SUCCESSFUL (total time: 67ms)

Win7 で MinGW/g++ を使用しています

なぜそれが機能するのですか?非プリミティブ型は値渡しできないと思っていた?!

4

3 に答える 3

9

非プリミティブ型は確かに値渡しできます。[expr.call](これは、C++ 標準のセクション 5.2.2で説明されています。)

ただし、特に C++03 コードでは、これがしばしば推奨されない理由がいくつかあります。

まず、大きなオブジェクトの場合、データがスタック上で渡されるため、参照渡しと比較すると効率が低下します。参照はスタック上で 1 ワードを使用するため、スタックを介して 1 ワードより大きいオブジェクトを渡すと必然的に遅くなります。

次に、値渡しはコピー コンストラクターを呼び出します (または、@templatetypedef が指摘するように、C++11 ではムーブ コンストラクターを呼び出す可能性があります)。この追加処理により、ある程度のオーバーヘッドが発生する可能性があります。

第 3 に、渡されたオブジェクトを変更するつもりだったかもしれませんが、コピーを (値で) 渡すことにより、関数内で行った変更は元のオブジェクトには影響しません。したがって、セマンティクスを正しくすることが重要です (つまり、オリジナルを変更するかどうか)。したがって、これは状況によっては潜在的なバグです。

最後に、コピー コンストラクターや代入演算子を持たない適切に記述されていないクラスがある場合、コンパイラは自動的に既定のクラスを生成します。これにより、浅いコピーが実行され、メモリ リークなどの問題が発生する可能性があります。これは、これらの特別なメソッドを実装することが非常に重要であるもう 1 つの正当な理由です。詳細については、次の記事を参照してください。

通常、C++03 コードではconst&、オブジェクトを変更するつもりがない場合は参照によって渡し、オブジェクト&を変更する必要がある場合は通常の参照によって渡します。パラメータがオプションの場合は、ポインタを使用してください。

これらの質問、特に移動のセマンティクスに関する議論にも、いくつかの適切な回答と議論が見られます。

C++11 の完全な答えはもっと複雑です。

おそらく、使用するアプローチの最良の要約は次のとおりです。

于 2013-08-21T00:42:30.207 に答える
3

あなたの教授は完全に間違っています.JAVAまたはC#について考えていたのでしょうか? C++ ではすべてが値渡しされます。何かを参照で渡すには、 & 修飾子を付けて渡す必要があります。

于 2013-08-21T00:42:02.690 に答える
1

非プリミティブ型は、実際に C++ で値渡しできます。これを行おうとすると、C++ はコピー コンストラクター(C++11 では場合によってはムーブ コンストラクター) と呼ばれる特別な関数を使用して、パラメーターを引数のコピーとして初期化します。コピー コンストラクターと代入演算子の記述は、C++ のトリッキーな部分であることが知られています (間違えるのは簡単で、正しくするのは難しいです)。コピー コンストラクターの記述に失敗したり、誤って記述したりすると、プログラムがクラッシュしやすくなり、新しい C++ プログラマーにとってよくある混乱の原因となります。

オブジェクトをインテリジェントにコピーする関数を作成する方法について詳しく知るには、「C++ Rule of 3」または「コピー コンストラクター代入演算子」を Google で検索することをお勧めします。これを行う方法を理解するには少し時間がかかりますが、概念を理解すればそれほど難しくありません。

お役に立てれば!

于 2013-08-21T00:41:59.820 に答える