web-dev-qa-db-ja.com

ベクトルメンバー変数への参照を返す

クラスのメンバーとしてベクターを持っているので、後で変更できるように、getVector()関数を使用してベクターへの参照を返します。関数getVector()をconstにしたほうがよいのではないでしょうか?ただし、次のコードで「型のバインディング参照で修飾子が削除されました...」というエラーが発生しました。何を変更する必要がありますか?

class VectorHolder
{
public:
VectorHolder(const std::vector<int>&);
std::vector<int>& getVector() const;

private:
std::vector<int> myVector;

};

std::vector<int> &VectorHolder::getVector() const
{
return myVector;
}
28
arjacsoh

これはconstメンバー関数であるため、戻り値の型を非const参照にすることはできません。 constにする:

const std::vector<int> &VectorHolder::getVector() const
{
   return myVector;
}

今は大丈夫です。

なぜ大丈夫ですか? constメンバー関数では、すべてのメンバーがconstになり、変更できないようになります。つまり、myVectorconstになります。関数内のベクトル。これがreferenceを返す場合、戻り型constも作成する必要がある理由です。

ここで、cannotを変更しますsameオブジェクト。できることとできないことを確認してください。

 std::vector<int> & a = x.getVector();       //error - at compile time!

 const std::vector<int> & a = x.getVector(); //ok
 a.Push_back(10);                            //error - at compile time!

 std::vector<int>  a = x.getVector();        //ok
 a.Push_back(10);                            //ok

ところで、そもそもなぜこのようなVectorHolderが必要なのか疑問に思っています。

33
Nawaz

次のように、constとmutableの両方のバリアントを宣言することは珍しいことではありません。

std::vector<int>& VectorHolder::getVector() {
  return myVector;
}
const std::vector<int>& VectorHolder::getVector() const {
  return myVector;
}

プログラムの根本的な問題は、constメソッドから非const参照を返すことです。

std::vector<int>& VectorHolder::getVector() const {
  return myVector; // << error: return mutable reference from const method
}

したがって、次の形式を使用してconstにします。

const std::vector<int>& VectorHolder::getVector() const {
  return myVector; // << ok
}

これが非constメソッドにある場合、またはクライアントが非const参照を保持している場合は、非constメソッドを合法的に使用できます。

std::vector<int>& VectorHolder::getVector() {
  return myVector; // << ok
}

最後に、値を返すことができます(場合によって):

std::vector<int> VectorHolder::getVector() const {
  return myVector; // << ok
}

コピーには突然変異が不要であり、内部データにさらされないためです。

そのため、両方のバリアントを頻繁に宣言することになります。

両方を宣言した結果は次のとおりです。

VectorHolder m;
const VectorHolder c;

m.getVector().size(); // << ok
c.getVector().size(); // << ok - no mutation

m.getVector().Push_back(a); // << ok
c.getVector().Push_back(a); // << error: attempt to mutate const reference because the const vector is returned

そのため、すべてがうまく機能します(メソッドの冗長性は別として)。

14
justin

関数getVectorは、constとして宣言できます。変更可能な参照が返されるため、実際の関数はクラス内の何も変更しませんが、呼び出し元は内部データを変更できます。

次のように宣言します。

std::vector<int>& getVector();

変更できないベクトルを関数で返すには、ベクトルと関数の両方でconst修飾子を使用します。

const std::vector<int>& getVector() const;

その理由は、constメンバー関数はconst参照のみを返す必要があるためです。これは、const関数では、すべてのデータメンバーが定数になるためです。

したがって、このようにgetVector()を宣言する必要があります。

std::vector<int> &VectorHolder::getVector() const;
0
Lev