2011-12-05 15 views
25

私はクラスのメンバとしてベクトルを持っており、後でそれを変更できるように、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; 
} 

答えて

27

メンバー関数constであるため、戻り値の型は非const参照ではありません。それを作るconst

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

今は大丈夫です。

なぜそれはいいですか? constメンバ関数では、すべてのメンバはconstになります。つまり、 constベクトルであるため、constも作成しなければならない場合は、myVectorが変更されます。 参照を返します。

今あなたはできません同じオブジェクトを変更することはできません。あなたは何ができるかを参照してくださいと何をすることはできません。あなたが最初の場所でVectorHolderなどを必要とする理由

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 

ちなみに、私は思ったんだけど。

+0

は、あなたがそれを返すコードから後で返さベクトルを修正するために、その後は不可能である:

したがって、あなたは()は、この方法で、それぞれgetVectorを宣言する必要がありますか? – arjacsoh

+0

@arjacsoh:それは異なります。編集を参照してください。 – Nawaz

13

それはそうのように、両方のconstおよび可変バリアントを宣言することは珍しいことではありません:あなたのプログラムと

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 

のですべてが(離れ方法の冗長性から)うまくうまくいきます。

2

getVectorは、constと宣言できます。実際の関数はクラス内の何も変更しませんが、呼び出し側は内部データを変更することができます。

としてそれを宣言します。あなたは機能を変更することはできませんベクトルを返すようにしたい場合は、ベクターと機能の両方にconst修飾子、

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

使用を:

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

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

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

上記にかかわらず、おそらく内部コンテナを公開するのは良い考えではありません。ベクタからマップに移行することをいつか決めると、ユーザーに影響が及ぼされます。代わりにイテレータを実装することをお勧めします。 – Lev

関連する問題