2011-10-18 5 views
5

次のエラーが発生していますerror: invalid conversion from ‘const int*’ to ‘int*’ 次は私のプログラムですstd :: set要素のアドレスを取っているときに 'const int *'から 'int *'への無効な変換

#include <set> 
int main (int argc, char **argv) { 
    std::set<int> intSet; 
    intSet.insert(1); 
    intSet.insert(2); 
    intSet.insert(3); 
    intSet.insert(4); 
    intSet.insert(5); 

    int *pAddress = &(*(intSet.find(4))); 
} 

std::setの要素のアドレスが必要です。このコードはMicrosoftコンパイラでコンパイルエラーは発生しませんが、g++はこのコンパイルエラーを出しています。

+0

std :: setの要素は、定数の場合は定数です。どのようなMSコンパイラを使用していますか? – cpx

+0

Visual Studio 2005 – Avinash

+2

VS2005のバグで、std :: setを変更することができません。 – cpx

答えて

5

std::setの各要素がT constとして格納されており、その理由があります。

std::setには、値のコピーが1つだけ含まれているためです。 は変更不可能にする必要があります。そうしないと、その値がセット内に既に存在するものに変更されます。要素が可変たとしても

std::set::findconstメンバ関数であるため、この機能でintSet不変で、効果的に各要素になるだろうので、あなたは、変更値ことができないであろう不変iteratorが返されます。コールサイトで値を変更します。

ザ・のみアドレスを取得したいが、このです:

int const *paddress = &(*(intSet.find(4))); //const int* is same as int const* 

は、クラスができるように、セットの値は不変であることを意味している、しかし

//DANGEROUS - DONT DO IT 
int *paddress = const_cast<int*>(&(*(intSet.find(4)))); //will compile, 
                 //but it is dangerous! 

//you might accidentally write 
*paddress = 10; //undefined behaviour, 
       //though the compiler will let you write this 
+0

要素のアドレスが必要なだけなので、キャストしないように型キャストできますか? – Avinash

+0

@Avinash:I私の答えにもっとたくさんのものを加えました。 – Nawaz

+0

Set要素は 'T const'ではなく' T'として格納され、順序に影響を与えない限り変更することができます。 GCCの行動は、より安全ではあるが、不適合である。 –

0

const_castを使用しないでください。すべての要素が一意であることを保証します。非constポインタを指定すると値を変更するのが簡単になり、設定したテンプレートクラス(http://msdn.microsoft.com/en-us/library/e8wh7665(VS.80).aspx)のデザインが壊れてしまいます。

あなたはそのようにそれの前にある「ポーラ」持っている最後の行を変更する必要があります。FYI

const int *pAddress = &(*(intSet.find(4))); 

:あなたのコードは、2010年

1

GCC definesのVisual Studioで同じコンパイルエラーを与えますset::iteratorset::const_iteratorとすると、リファレンスまたはset::find()の結果へのポインタをバインドすることができなくなります。この動作はC++ 11(キーが不変であり、set::iteratorが定数反復子であることを示しています)では許可されていますが、C++ 03では正しくありませんでした。

C++ 03では、セット内の要素の順序を壊す可能性があるため、セットの要素を変更しないでください。場合によっては、型がクラスであり、順序を定義するために一部のメンバーのみが使用されている場合は、他のメンバーを変更することが有効でした。 C++ 03標準ではこれが可能ですが、未定義の動作を与えるように順序を変更しないように注意する必要があります。 C++ 11では、これは許可されていません。

あなたが合法的に値を変更することはできないので、C++ 11用のコードを修正し、ポインタのconstにバインドすることで安全性を向上させることができます。

int const *pAddress = &(*(intSet.find(4))); 
+2

n3225の連想コンテナの要件では、「set」と「multiset」の場合、値の型はキーの型と同じです...連想コンテナのキーは** immutable * *。 "と "連想型コンテナの場合、値型がキー型と同じである場合、iteratorとconst_iteratorは両方とも**定数反復子**です。反復子とconst_iteratorが同じ型であるかどうかは指定されていません です。 - GCCが準拠していると思われるバグ報告の議論でも言及されています。 – UncleBens

+0

@UncleBens:私はこれらの節を持たないC++ 03を見ていましたが、iteratorはすべてのコンテナに対して「T」を指すイテレータタイプであると指定しています。私はC++ 11の答えを更新します。 –

関連する問題