2011-10-18 13 views
5

Aşağıdaki error: invalid conversion from ‘const int*’ to ‘int*’ hatası alıyorum ProgramımStd :: set element adresi kullanılırken ‘const int *’ - ‘int *’ arasında geçersiz dönüşüm

#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 öğesinin adresini istiyorum, Bu kod Microsoft derleyici ile herhangi bir derleme hatası vermez ama g++ bu derleme hatası veriyor.

+0

std :: set'in öğeleri, sabit tamsayılarınızda sabittir. MS derleyicisi ne kullanıyorsunuz? – cpx

+0

Visual Studio 2005 – Avinash

+2

VS2005'te std :: set'in değiştirilmesine izin veren bir hata. – cpx

cevap

5

Bu, std::set öğelerinin her öğesinin T const olarak depolandığından ve uygulamanın bunu yapması için bir nedeni olmasından kaynaklanır.

std::set'dan beri bir değerin tek bir kopyasını tam olarak içerir. Aksi halde, immutable yapmalıdır, aksi takdirde, bu değer kümede zaten var olan bir değere dönüşebilir. elemanlar değişken olsa bile

, std::set::find bir const üye fonksiyonudur ve bu nedenle bu işlevi intSetdeğişmez ve etkili bir şekilde her unsurlar haline gelecek, çünkü değişim değeri mümkün olmaz değişmez ayrıca, geri döndüğü yineleyici dahil olmak üzere ve aracılığıyla çağrı alanında değeri değiştirebilir.

sadece adres almak istiyorum şudur:

setin değerleri değişmez olmak içindir
int const *paddress = &(*(intSet.find(4))); //const int* is same as int const* 

olsa const_cast kullanmayın,

//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

Sadece öğenin adresine ihtiyacım olduğu için, – Avinash

+0

@Avinash: a cevabım için daha fazla içerik ekledi. – Nawaz

+0

Ayar öğeleri, "T" değil, "T const" olarak depolanır ve siparişi etkilemediğiniz sürece değiştirilebilir. GCC'nin davranışı, daha güvenli iken, uygunsuzdur. –

0

sınıf can böylece Tüm elemanların benzersiz olduğunu garanti eder. Size const işaretçisi vermemek, değeri değiştirmenizi çok kolaylaştıracak ve bu da set şablon sınıfının tasarımını bozacaktır (http://msdn.microsoft.com/en-us/library/e8wh7665(VS.80).aspx).

Öyle gibi önünde bir "const" olması son satırı değiştirmelisiniz: Bilginize

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

: Kodunuz 2010.

1

GCC defines Visual Studio özdeş derleme hata veriyor set::iterator, const referansı veya işaretçisini set::find() sonucuna bağlamanızı önleyen set::const_iterator olmalıdır. Bu davranış, C++ 11 (anahtarların değişmez olduğunu ve set::iterator sabit yineleyici olduğunu belirtir) tarafından izin verilir, ancak C++ 03'de yanlıştır.

C++ 03'te, bir kümenin öğelerini değiştirmemelisiniz çünkü bu, içindeki öğelerin sıralanmasını bozabilir. Bazı durumlarda, isteyebilirsiniz - tür bir sınıfsa ve siparişi tanımlamak için yalnızca bazı üyeler kullanılıyorsa, diğer üyeleri değiştirmek için geçerliydi. C++ 03 standardı buna izin verir, ancak siparişi, tanımlanmamış davranışlar verecek şekilde değiştirmemeniz konusunda dikkatli olmalısınız. C++ 11'de buna izin verilmez ve uygulama bunu engelleyebilir.

Sizin durumunuzda, değeri yasal olarak değiştiremezsiniz, böylece C++ 11 için kodunuzu düzeltebilir ve ayrıca bir işaretçiden yapıcıya bağlanarak güvenliğini artırabilirsiniz.

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

N3225 ilişkisel kapsayıcı gereksinimlerinde bu oldukça açık bir seçimdir: "Set" ve "multiset" için değer türü anahtar türüyle aynıdır ... ... İlişkili bir kapsayıcıdaki anahtarlar ** değişmezdir * * ". ve " adresindeki ilişkilendirme kapsayıcıları için, değer türü anahtar türüyle aynıdır, hem yineleyici hem de const_iterator ** sabit yineleyicilerdir **. Yineleyici ve const_iterator öğesinin aynı türde olup olmadığına bakılmaksızın belirtilmemiş." - Hata raporu tartışmasında bile GCC'nin uygun kabul edildiği belirtilmiştir. – UncleBens

+0

@UncleBens: Bu maddeler içermeyen C++ 03'e bakıyordum, ancak tüm kapsayıcılar için "yineleyici" nin "T" harfini gösteren bir yineleyici türü olduğunu belirtiyor. Cevabımı C++ 11 için güncelleyeceğim. –

İlgili konular