web-dev-qa-db-ja.com

constポインターを返すc ++ constメンバー関数。しかし、返されるポインターはどのようなconstですか。

これが尋ねられた場合は謝罪しますが、次のシーンリオでポインターを返すメンバー関数をc ++で作成するにはどうすればよいですか。 2.内部のジャンクは一定ですが、返されるポインターは変更できます。 3.ジャンクもポインターも変更できません。

そうですか:

  1. int *const func() const
  2. const int* func() const
  3. const int * const func() const

私が読んだチュートリアルのすべては、この区別をカバーしていません。

補足:メソッドがconstとして宣言されている場合、チュートリアルでは、パラメーターを変更しないと述べています。しかし、パラメーターがポインターの場合、これは十分に明確ではありません。私のパラメータは次のようにする必要がありますか?

a。 void func(const int* const x) const;
b。 void func(const int* x) const;
c。 void func(const int* const x) const;

36
Jor

どの本を読んだかわかりませんが、メソッドconstをマークすると、thisは_const MyClass*_ではなく_MyClass*_型になります。つまり、 mutableとして宣言されていない非静的データメンバーを変更したり、thisで非constメソッドを呼び出すことはできません。

戻り値について説明します。

1 int * const func () const

関数は定数であり、返されるポインターは定数ですが、「内部のジャンク」は変更できます。ただし、最終的な関数呼び出しは右辺値であり、非クラス型の右辺値はconstにはできないため、constポインターを返すことには意味がありません。つまり、constは無視されます。

2。 const int* func () const

これは便利なことです。 「ジャンクインサイド」は変更できません

3。 const int * const func() const

1の理由により、意味的に2とほぼ同じです。

HTH

68
Armen Tsirunyan

Constの一部の使用は、あまり意味がありません。

次の機能があるとします。

void myFunction (const int value);

Constは、関数内で値を変更してはならないことをコンパイラーに伝えます。この情報には、呼び出し元にとっての値はありません。値をどう処理するかを決定するのは、関数自体です。呼び出し元の場合、次の2つの関数定義はまったく同じように動作します。

void myFunction (const int value);
void myFunction (int value);

値は値で渡されるため、関数はローカルコピーを取得します。

一方、引数が参照またはポインターである場合、状況は大きく異なります。

void myFunction (const MyClass &value);

これは、値が参照によって渡されることを呼び出し元に伝えます(したがって、画面の背後では実際にはポインターです)が、呼び出し元は値を変更しないことを約束します。ポインターについても同じことが言えます。

void myFunction (const MyClass *value);

(パフォーマンス上の理由から)MyClassにポインターを渡しますが、関数は値を変更しないことを約束します。

次のように書く場合:

void myFunction (MyClass * const value);

その後、私たちは彼の最初の状況に戻りました。 myFunctionはポインターを取得します。ポインターは値で渡され、constです。 MyFunctionはポインター値のコピーを取得するため、呼び出し側にとってはconstであるかどうかは関係ありません。最も重要なことは、ポインター変数自体はconstであるが、その内容はそうではないため、myFunctionがvalueの内容を変更できることです。

戻り値についても同様です:

const double squareRoot(double d);

これは意味がありません。 squareRootはconst doubleを返しますが、これは「値によって」渡されるため、独自のローカル変数にコピーする必要があるため、必要に応じて何でもできます。

一方:

const Customer *getCustomer(char *name);

GetCustomerが顧客へのポインタを返し、顧客のコンテンツを変更することは許可されていないことを教えてくれます。

実際、関数が与えられた文字列を変更することを期待していないので、char-pointer-contentsもconstにする方が良いでしょう:

const Customer *getCustomer(const char *name);
15
Patrick

int *const func() const

いくつかの場合を除いて、ここでconstを観察することはできません

  • funcのアドレスを取得します。
  • C++ 0xでは、funcオペランドとして関数呼び出し構文を使用してdecltypeを直接呼び出すと、_int * const_が生成されます。

これは、純粋なポインター値、つまり実際にポインター変数に格納されていないポインター値を返すためです。これらの値は変更できないため、const修飾されていません。 constを削除しても、obj.func() = NULL;とは言えません。どちらの場合でも、式obj.func()の型は_int*_であり、変更できません(誰かがすぐに標準を引用し、「rvalue」という用語を思い付くでしょう)。

そのため、戻り値を使用するコンテキストでは、違いを把握することはできません。宣言または関数全体を参照する場合にのみ、違いに気付くでしょう。

const int* func() const

これは、ボディが_return &this->intmember;_のような場合に通常行うことです。 *obj.func() = 42;を実行してintメンバーを変更することはできません。

const int * const func() const

これは最初の2つの組み合わせです:)

Constへのポインターを返すことは非常に理にかなっていますが、constポインターを返す(変更することはできません)ことは通常、値を追加しません(ユーザーエラーの防止やコンパイラーの最適化を追加できると言う人もいます)。

これは、戻り値が関数の呼び出し元に属しているためです。つまり、戻り値は独自のコピーであるため、(他の何かを指すように)変更しても問題にはなりません。ただし、コンテンツは呼び出し側に「属さない」ため、関数の実装者は読み取り専用情報であるという契約を結ぶ場合があります。

定数メンバー関数は、クラスの状態を変更しないことを約束しますが、これは実際には必ずしもコンパイラーによって強制されるわけではありません。クラス自体にポインターまたは参照が含まれている場合、constメンバー関数はポインターを定数ポインターに変換しますが、constへのポインターを作成しないため、const_castまたはmutableメンバーを参照しません定数への参照に。これらがクラスのコンポーネントである場合(およびそのようなコンポーネントは多くの場合ポインタで表されます)、関数の状態を変更できます。

可変メンバーは、クラスが内部状態を変更せずに変更できるようにするために存在します。これらは通常、次のものに適用できます。

  • 読み取りでもロックするミューテックス。
  • 遅延ロードされたデータ、つまり、最初にアクセスされたときに入力されるデータ。
  • 参照カウントされたオブジェクト:別のビューアがある場合、参照カウントを増やしたいので、それを読むためだけに状態を変更します。

const_castは一般に「ハック」と見なされ、他の誰かがコードを適切にconst-correctで記述していないときによく行われます。ただし、次の状況では価値があります。

  • 1つがconstで、1つが非constであり、constがconst参照を返し、non-constが非const参照を返す複数のオーバーロード。ただし、それ以外は同じです。コードを複製する(単純なデータメンバgetでない場合)のは良いアイデアではないため、一方を他方の観点から実装し、const_castを使用してコンパイラを回避します。

  • 特にconstオーバーロードを呼び出したいが、非const参照が必要な場合。最初にconstにキャストします。

1
CashCow

Constメソッドは、メンバーを変更できないようにします。ポインターの場合、これはポインターを再割り当てできないことを意味します。あなたの心の欲望へのポインタによって指し示されたオブジェクトを変更することができます。

ポインターは値(コピー)で返されるため、呼び出し側はそれを使用してクラスのポインターメンバーを変更することはできません。したがって、戻り値にconstを追加しても何も追加されません。

ポインタへの参照を返す場合、状況は異なります。ポインターがconstでなかった場合、これは、値を変更する権限を持たない関数がこの権利を呼び出し元に付与していることを意味します。

例:

class X
{
    int* p;
public:
    int* get_copy_of_pointer() const //the returned value is a copy of this->p
    { 
        *p = 42;  //this being const doesn't mean that you can't modify the pointee
        //p = 0;  //it means you can't modify the pointer's value
        return p; 
    }
    int* const& get_reference_to_pointer() const //can't return a reference to non-const pointer
    {
        return p;
    }
};
0
visitor