C ++ eşleme türü bağımsız değişkeni [] kullanırken neden boş bir kurucu gerektiriyor?


101

Ayrıca C ++ standart listesi ve varsayılan oluşturulabilir türlere bakın

Büyük bir sorun değil, sadece sınıfımın belirli argümanlar olmadan somutlaştırılmasını istemediğim için sinir bozucu.

#include <map>

struct MyClass
{
    MyClass(int t);
};

int main() {
    std::map<int, MyClass> myMap;
    myMap[14] = MyClass(42);
}

Bu bana aşağıdaki g ++ hatasını veriyor:

/usr/include/c++/4.3/bits/stl_map.h:419: hata: 'Sınıfım ()' çağrısı için eşleşen işlev yok

Varsayılan bir kurucu eklersem bu iyi derler; Yanlış sözdiziminden kaynaklanmadığına eminim.


Yukarıdaki kod, MyType için bir typedef verilmesi ve sınıfın sonuna bir noktalı virgül eklenmesi koşuluyla, MinGW (g ++ 3.4.5) ve MSVC ++ 2008'de çok iyi derlenir. Başka bir şey yapıyor olmalısınız (örn. Bb'de belirtildiği gibi [] operatörü çağırın) - lütfen tam kodu gönderin .
j_random_hacker

Ah, evet, haklısın. Yapacağım.
Nick Bolton

Evet, myMap'i kullanmadan harita sınıfı için neyin derlenmesi gerektiğini bilemezsiniz. Hangi stl kitaplık sağlayıcısı ve sürümü de yardımcı olabilir.
Greg Domjan

Yanıtlar:


168

Bu sorun [] işleciyle birlikte gelir. SGI belgelerinden alıntı:

data_type& operator[](const key_type& k)- Belirli bir anahtarla ilişkili nesneye bir başvuru döndürür. Harita zaten böyle bir nesne içermiyorsa operator[] , varsayılan nesneyi ekler data_type().

Varsayılan kurucunuz yoksa, ekle / bul işlevlerini kullanabilirsiniz. Aşağıdaki örnek iyi çalışıyor:

myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;

11
Mükemmel cevap - emplaceC ++ 11'e kısa bir alternatif olarak da dikkat edin insert.
prideout

3
Bunun nedeni nedir std::<map>::value_typeorada insertçağrı?
thomthom

1
Varsayılan kurucunun neden kullanıcı tanımlı olması gerekiyor?
schuess

@schuess Bunun neden olduğunu görmüyorum: = defaultsadece iyi çalışmalı.
underscore_d

'Harita halihazırda böyle bir nesne içermiyor' koşulu çalışma zamanında değerlendirilecektir. Neden derleme zamanı hatası?
Gaurav Singh

7

Evet. STL kapsayıcılarındaki değerler, kopyalama anlamlarını korumalıdır. IOW, ilkel türler (örneğin int) gibi davranmaları gerekir, bu da diğer şeylerin yanı sıra varsayılan olarak yapılandırılabilir olmaları gerektiği anlamına gelir.

Bu (ve diğer gereksinimler) olmadan, STL konteynerlerinin uygulandığı veri yapıları üzerinde çeşitli dahili kopyalama / taşıma / değiştirme / karşılaştırma işlemlerini uygulamak gereksiz bir şekilde zor olacaktır.

C ++ Standardına referansla, cevabımın doğru olmadığını görüyorum. Varsayılan yapım aslında bir gereklilik değildir :

20.1.4.1'den itibaren:

Varsayılan kurucu gerekli değildir. Belirli kapsayıcı sınıfı üye işlev imzaları, varsayılan kurucuyu varsayılan bağımsız değişken olarak belirtir. T () iyi tanımlanmış bir ifade olmalıdır ...

Bu nedenle, kesin olarak söylemek gerekirse, değer türünüzün yalnızca imzasında varsayılan kurucuyu kullanan bir konteyner işlevini kullanıyorsanız varsayılan olarak oluşturulabilir olması gerekir.

STL kaplarında depolanan tüm değerlerden gerçek gereksinimler (23.1.3) CopyConstructibleve Assignable.

Aynı zamanda, özel kaplar için başka özel gereksinimler de vardır, örneğin Comparable(örneğin bir haritadaki anahtarlar için).


Bu arada, aşağıdaki hiçbir hata gelmeden derlenir :

#include <map>

class MyClass
{
public:
    MyClass(int t);
};

int main()
{
    std::map<int, MyClass> myMap;
}

Yani bu bir g ++ sorunu olabilir.


2
Bb [] operatörü ile ilgili bir şey olabilir mi?
Nick Bolton

13
Bu kod muhtemelen myMap []
aramadığınız için derleniyor

4

Stl :: map depolanmış türünün gereksinimlerini kontrol edin. Çoğu stl koleksiyonu, depolanan türün bazı belirli özellikleri (varsayılan kurucu, kopya yapıcı, vb.) İçermesini gerektirir.

Stl :: map, argümansız kurucuya ihtiyaç duyar, çünkü bu, harita tarafından henüz tutulmamış olan anahtarla [] operatörü çağrıldığında kullanılır. Bu durumda [] operatörü, yeni anahtar ve parametresiz kurucu kullanılarak oluşturulan değerden oluşan yeni girişi ekler. Ve bu yeni değer daha sonra döndürülür.


-2

Kontrol eğer:

  • ';' Unuttunuz sınıf bildiriminden sonra.
  • MyType buna göre bildirilmiş olmalıydı.
  • Orada varsayılan kurucu yok ...

Std :: map bildirimi doğru görünüyor sanırım.


Varsayılan bir kurucu eklersem iyi derler.
Nick Bolton

-2

Büyük olasılıkla std :: pair gerektirdiğinden. std :: pair, değer semantiğini kullanan iki değeri tutar, bu yüzden onları parametreler olmadan başlatabilmeniz gerekir. Bu nedenle kod, harita değerlerini arayana döndürmek için çeşitli yerlerde std :: pair kullanır ve bu genellikle boş bir çiftin somutlaştırılması ve yerel çifti döndürmeden önce değerlerin ona atanması ile yapılır.

Bunu bir harita <int, smartptr <MyClass>> kullanarak akıllı işaretçilerle aşabilirsiniz, ancak bu, boş işaretçileri kontrol etmenin ek yükünü ekler.


2
+0. <T, U> çifti, varsayılan kuruculara sahip olmayan T ve U türlerinde gayet iyi kullanılabilir - bu durumda kullanılamayan tek şey, <T, U> çiftinin kendi varsayılan kurucusudur. <K, V> haritasının iyi kalitede hiçbir uygulaması bu varsayılan kurucuyu kullanmaz çünkü K ve V'nin ne olabileceğini sınırlar.
j_random_hacker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.