どのようにパスオブジェクト機能にはC++?
-
22-09-2019 - |
質問
これまでC++によるプログラムが、今ではもうほとんど経験がJava.い方法についてのガイダンスにパスオブジェクト機能が可能です。
いただいたパスへのポインタを参照、または非ポインタと非参考価値?たのを覚えているJavaがないなどの問題からその変数を保持するのオブジェクト。
いきものがそれぞれのオプション
解決
ルールの目安 C++11:
峠 による価値, る場合を除き、
- する必要はないの所有権オブジェクトの簡単なエイリアスない場合、 通
const
参考, - 必ず変異のオブジェクトの場合、利用 パスによる非
const
lvalue参照, - 渡ししますの物由来のクラスを基底クラスで、その場合、必要なもの パス参照.(使用前のルールかどうかを
const
参考ます。)
通りすがりのポインタはほぼいます。オプションパラメータをベストとして表現 std::optional
(boost::optional
高齢std lib)、エイリアシングを行うフレンズに参考にする。
C++11の意味ようとしているの還元による価値をより魅力的で複雑なオブジェクト。
ルールの目安 C++03:
パス引数 による const
参考, る場合を除き、
- にあたっては、変更の内部機能の変化に反映されるべき外の場合、 パスによる非
const
参考 - この関数は呼び出しなし引数の場合、通ポインタ位置することにより、ユーザーはパス
NULL
/0
/nullptr
代;適用前のルールかどうか判断すべき パスによりポインタconst
引数 - その種類は、 渡されたコピー
- 彼らは変更される内側の機能等の変更すべき ない れ以外の場合、できる パスコピー 代替するパスによる前のルールをコピー関数の中で)
(ここでは、"通価値"を"パスコピー"ですが、通りすがりの価値は必ずコピーを作成し、C++03)
あこれ、こうした数少ない初心者の規則取得しまいます。
他のヒント
若干の違いがありますが呼び出し規約のC++およびJava.C++が技術的に言えば二つの条約:パスによる価値-パススルーによる参照は、一部の文学を含む第三のパススルーによるポインターンして実際にパススルーによる価値のポインタタイプ)です。その上に追加することができますconstらしさの型引数の向上の意味論。
パス参照
通りすがりの参考に機能概念的にはお客オブジェクトインスタンスではなくコピーします。の基準は概念的にはエイリアスのオブジェクトで使用された呼び出し側コンテキストではnullになります。すべての操作内で行われる機能のオブジェクト以外の機能です。このコンベンションは利用できませJava、C
パスによる価値およびパススルーによるポインタ)
のコンパイラを生成するオブジェクトのコピーを呼び出し側コンテキストとそのコピーの機能です。すべての操作内で行われる機能のためのコピーではなく、外部要素となります。この条約のためのプリミティブ型は、Java.
る特別バージョンではポインタ(住所、オブジェクト)の機能です。この機能のポインタ、およびすべての業務の適用のポインターそのもののコピー(ポインタの操作に逆参照さのポインタを適用し、オブジェクトインスタンスでこのメモリ位置の機能は副作用があります。の効果をパススルーによる価値のポインタをオブジェクトの内部機能の変更に外部価値とのパススルーによる参照することも可能でオプション値(nullを渡ポインタ.
この条約を利用した場合の機能ニーズへの変更は、外部変数、およびコンベンション用のJava参考:を参考にコピーされ、その参照オブジェクトは同じです:変更の参照ポインは見えません外部の機能が変化したメモリ。
追加constの方程式
C++を割り当てることができ定ネジ定義の変数へのポインタと参照です。できると宣言すること可変することができると宣言することを参考に一定のインスタンスは、定義することができすべてのポインタ定数オブジェ、定のポインタを変更可能なオブジェクトは、一定のポインタ定数です。逆に、Javaできるだけ定義しレベルの定さ(最終キーワード):この変数(インスタンスのためのプリミティブ型、参考のための参照型のものを定義することはできませんへの参照を変更不能な要素にない場合にクラスは不変なので).
ここに広く用いられていC++の呼び出しコンベンションに出かけていく。合物を小とすることができますのオブジェクトによる値です。のコンパイラを生成するコピーがコピーではない高価で動作します。その他の型の場合、機能は変わりませんのオブジェクトとすることができますの参考定数インスタンス(通常は定するために、参考のタイプです。このことはコピーのオブジェクトが通過する機能です。しかし同時にコンパイラが保証されるこのオブジェクトが変更されませんの機能です。
経験則
このはつかの基本的なルールに従:
- 好みのパススルーによる価値のためのプリミティブ型
- 好みのパススルーによる参照を参照一定のその他の種類
- この機能改変を必要引用パススルーによる参照
- そうでない場合は、引数はオプション使用のパススルーによるポインタ(一定の場合はオプション値を改変することはできません)
ありその他の逸脱からこれらの規則は、取り扱いの所有のオブジェクトです。があるオブジェクトを動的に割り当てられ、なければ割と削除(もしくは[]バージョンが決まる。のオブジェクトや機能の破壊のオブジェクトは、オーナーの資源です。時に動的に割り当てオブジェクトが作成した本ソフトウェアのユーザコードの所有権が移動し、異なる要素では通常行っていパススルーによるポインタでの意味、可能な場合はスマートポインタ.
側の注意
ことが重要で主張の重要性の違いをC++およびJava参照です。C++参照の概念のインスタンスオブジェクトではなく、アクセス用メソッドです。最も単純な例は、実装スワップ機能:
// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
Type tmp = a;
a = b;
b = tmp;
}
int main() {
Type a, b;
Type old_a = a, old_b = b;
swap( a, b );
assert( a == old_b );
assert( b == old_a );
}
スワップ機能上 変化 その引数の参照です。最も近いコードに"Java:
public class C {
// ...
public static void swap( C a, C b ) {
C tmp = a;
a = b;
b = tmp;
}
public static void main( String args[] ) {
C a = new C();
C b = new C();
C old_a = a;
C old_b = b;
swap( a, b );
// a and b remain unchanged a==old_a, and b==old_b
}
}
は、Javaバージョンのコードのコピーを参照の内部でもないが、実際のオブジェです。Java参照をCのポインタなしのポインタの演算が取得した価値。
考慮すべきいくつかの例があります。
パラメータ
( "OUT" と "イン/アウト" パラメータ)を変更void modifies(T ¶m);
// vs
void modifies(T *param);
この場合は、ほとんどのスタイルについてです:あなたは、コードは次のようになりたいです。の呼び出し(OBJ)またはの呼び出し(&OBJ)の?しかし、差事項二点あります。オプションの場合は、以下の、そしてあなたが演算子をオーバーロードする際の基準を使用するには、
...とオプション
void modifies(T *param=0); // default value optional, too
// vs
void modifies();
void modifies(T ¶m);
パラメータは変更されません。
void uses(T const ¶m);
// vs
void uses(T param);
これは興味深いケースです。親指のルールは種類が値で渡され、「コピーするには安い」である - 他がconstの参照によって渡されながら - これらは一般的に小さなタイプ(常にではない)です。しかし、あなたは関係なく、あなたの関数内のコピーを作成する必要がある場合、あなたは値ので渡す必要があります。 (はい、この露出する実装の詳細のビットするC'estルC ++ )
...とオプション
void uses(T const *param=0); // default value optional, too
// vs
void uses();
void uses(T const ¶m); // or optional(T param)
すべての状況との間に、ここで少なくとも違いが、ありますので、あなたの人生が最も簡単になる方を選択します。
のConst値によって実装の詳細
でありますvoid f(T);
void f(T const);
値渡しするとこれらの宣言は、実際にのとまったく同じ機能です!の、constが純粋に実装の詳細です。 それを試してみてください:の
void f(int);
void f(int const) { /* implements above function, not an overload */ }
typedef void NC(int); // typedefing function types
typedef void C(int const);
NC *nc = &f; // nc is a function pointer
C *c = nc; // C and NC are identical types
値で渡します。
void func (vector v)
関数、すなわち機能が実行されている間、その値を変更することから、他のスレッドを防ぐために、元の変数を変更するだけでなく、より機能を防止するために、環境から完全に分離する必要がある値渡し変数
欠点は、オブジェクトをコピーするために費やしたCPUサイクルと余分なメモリです。
const参照で渡します。
void func (const vector& v);
このフォームエミュレートが通過することによって値の挙動をコピーオーバーヘッドを除去しつつ。この関数は、元のオブジェクトへの読み取りアクセスを取得しますが、その値を変更することはできません。
欠点は、スレッドセーフである:それはまだ実行ている間、別のスレッドが元のオブジェクトに加えられた変更は、関数の内部に表示されます。
非const参照渡し:
void func (vector& v)
この機能を使用し、最終的に呼び出し側によって使用されます変数に何らかの値を書き戻す必要があります。
ただ、const参照の場合と同様に、これはスレッドセーフではありません。
パスのconstポインタによって:
void func (const vector* vp);
異なる構文、プラス呼び出す関数は、それが通過する有効なデータを持っていないことを示すためにNULLポインタを渡すことができるという事実を除いてのconst参照渡しとして、機能的には同じ
スレッドセーフではありません。
パス非constポインタによって:
void func (vector* vp);
非const参照と同様に、。関数が値を書き戻すことになっていない場合に、発信者は通常、NULLに変数を設定します。この規則は、多くのglibcのAPIに見られます。例:
void func (string* str, /* ... */) {
if (str != NULL) {
*str = some_value; // assign to *str only if it's non-null
}
}
参照/ポインタによって、すべてのパスのようなだけで、スレッドセーフではありません。
誰もあなたがオブジェクトのクローンを作成するものを持っていけない場合に呼び出されたオブジェクトのデフォルトのコピーコンストラクタC ++の関数にオブジェクトを渡し、その後にそれを渡すと、私は、それに追加してい言及していないので、あなたが代わりにCで問題となる元のオブジェクトのオブジェクトのコピーに反映されますオブジェクトの値を変更するときの方法、++、あなたはすべてのクラスがポインタであることを属性を作るのであれば、その後、コピーコンストラクタがコピーされますポインタ属性のアドレスは、そうもポインタがアドレスを属性に格納された値の変更を操作するオブジェクト上のメソッド呼び出しは、これは同じJava振る舞うことができるが、それを忘れていけないので、パラメータとして渡された元のオブジェクトに反映させる場合すべてのクラス属性がポインタである必要があり、また、あなたはポインタの値を変更する必要があり、コードの説明と非常に明らかであろう。
Class CPlusPlusJavaFunctionality {
public:
CPlusPlusJavaFunctionality(){
attribute = new int;
*attribute = value;
}
void setValue(int value){
*attribute = value;
}
void getValue(){
return *attribute;
}
~ CPlusPlusJavaFuncitonality(){
delete(attribute);
}
private:
int *attribute;
}
void changeObjectAttribute(CPlusPlusJavaFunctionality obj, int value){
int* prt = obj.attribute;
*ptr = value;
}
int main(){
CPlusPlusJavaFunctionality obj;
obj.setValue(10);
cout<< obj.getValue(); //output: 10
changeObjectAttribute(obj, 15);
cout<< obj.getValue(); //output: 15
}
あなたはメモリリークのための傾向があるとデストラクタを呼び出すことを忘れないでください、ポインタ、と関わる多くのコードを書いて終わるされるように、しかし、これは良いアイデアではありません。そして、このC ++を避けるために、ポインタを含むオブジェクトが他のオブジェクトのデータを操作を停止します関数の引数に渡されたときに新しいメモリを作成するコピーコンストラクタを持っている、Javaは値渡しを行い、それがコンストラクタをコピーする必要はありませんので、値は、参照です。
が通過するオブジェクトとしての機能をパラメータ:
- パス参照
- パスによる価値
- 追加の定数、パラメータ
を以下の例:
class Sample
{
public:
int *ptr;
int mVar;
Sample(int i)
{
mVar = 4;
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value of the pointer is " << *ptr << endl
<< "The value of the variable is " << mVar;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
char ch;
cin >> ch;
}
出力:
言いsomeFunc
の値をポインタ-17891602
変数の値は4
以下の方法に渡す引数をパラメータの機能にはC++.
1.による値です。
// passing parameters by value . . .
void foo(int x)
{
x = 6;
}
2.による参考値です。
// passing parameters by reference . . .
void foo(const int &x) // x is a const reference
{
x = 6;
}
// passing parameters by const reference . . .
void foo(const int &x) // x is a const reference
{
x = 6; // compile error: a const reference cannot have its value changed!
}
3.によるオブジェクトです。
class abc
{
display()
{
cout<<"Class abc";
}
}
// pass object by value
void show(abc S)
{
cout<<S.display();
}
// pass object by reference
void show(abc& S)
{
cout<<S.display();
}