Neden kullanım = C ++ temel bir tür başlatmak için?

oy
8

Çalıştığım yerde insanlar çoğunlukla nesnelerin iyi C ++ kullanılarak ilklendirilmiş düşünüyorum - ilkel türleri = operatörü ile başlatılmak gerektiğini dikkate alarak, stil inşaat (parantez ile):

std::string strFoo( Foo );
int nBar = 5;

Kimse şeyler bu şekilde tercih etmelerinin olsa açıklayabilmek gibi görünüyor. Bunu görebiliyorum std::string = Foo;bunun fazladan bir kopyasını içeren çünkü verimsiz olurdu, ama sadece ne sürgün nesi =tamamen operatör ve her yerde parantez kullanarak?

ortak bir kongre var mı? Bunun arkasındaki düşünce nedir?

Oluştur 09/12/2008 saat 18:52
kaynak kullanıcı
Diğer dillerde...                            


9 cevaplar

oy
17

= Operatörü ile veya bir yapıcı çağrısıyla başlatılıyor değişkenler o tarzın sadece bir soru, anlamsal olarak aynıdır. daha doğal okur beri, = operatörünü tercih ederim.

= Operatörünü kullanarak genellikle fazladan bir kopyasını oluşturmaz - sadece normal yapıcı çağırır. Temel olmayan tipleri ile, bu tek beyanları ile aynı zamanda meydana gelen başlangıç tanımlamaları için Bununla birlikte, dikkat edin. Karşılaştırmak:

std::string strFooA("Foo");  // Calls std::string(const char*) constructor
std::string strFoo = "Foo";  // Calls std::string(const char*) constructor
                             // This is a valid (and standard) compiler optimization.

std::string strFoo;  // Calls std::string() default constructor
strFoo = "Foo";      // Calls std::string::operator = (const char*)

Eğer önemsiz olmayan varsayılan kurucuya sahip olduğunda, ikinci yapı biraz daha verimsiz olabilir.

C ++ standart , bölüm 8.5, paragraf 14 durumları:

Aksi halde (kalan kopyalama başlatma durumlar için yani), geçici oluşturulur. Hedef türü ya da (13.3.1.4) numaralandırılan türetilmiş bir sınıf, en iyi bir kaynak türü dönüştürmek Kullanıcı tanımlı dönüşüm sekansları aşırı çözünürlüğü (13.3) içinden seçilir. Şekilde seçilir kullanıcı tanımlı dönüşüm hedef Çeşidi ev elemeleri ile, türü kullanıcı tanımlı işlev çağrısında tarafından döndürülen türüdür, geçici olarak başlatıcı ifade dönüştürmek için çağrılır. Dönüşüm yapılır ya da belirsiz edilemezse, başlatma kötü oluşturulur. Başlatıldı nesne daha sonra yukarıdaki kurallara göre geçici olarak doğrudan-başlatılmış olup. 87 ) Bazı durumlarda, bir uygulama direkt olarak obje başlatarak geçici ortadan kaldırmak için izin verilir; 12.2 bkz.

bölüm 12.2 devletlerin Bölüm:

Geçici nesnenin oluşturulması önlenir bile, bütün semantik kısıtlamalar geçici nesne oluşturulduğu sanki saygı gösterilmelidir. [Örnek: kopya yapıcısı olarak adlandırılan olmasa bile, böyle erişilebilirlik (11) gibi tüm semantik kısıtlamalar, memnun olacaktır. ]

Cevap 09/12/2008 saat 18:57
kaynak kullanıcı

oy
11

Ben sadece başka saçma LITB yazı için ihtiyacı hissetti.

string str1 = "foo";

denir kopyalamaya karşı başlatma derleyici ne herhangi geçiciri elide etmezse, çünkü:

string str1(string("foo")); 

yanında kullanılan dönüşüm yapıcı örtülü olduğunu kontrol ediyor. Aslında tüm örtük dönüşümler kopya başlatma açısından standardında tanımlanmıştır. T tip türü U bir kapalı dönüştürme durumunda geçerli olduğu söylenir

T t = u; // u of type U

geçerlidir.

constrast,

string str1("foo");

yazılır ve denir tam olarak ne yaptığını direkt başlatma . Ayrıca açık kurucular ile çalışır.

Bu arada, -fno-elide-Kurucular kullanarak geçicilerin eliding devre dışı bırakabilirsiniz:

-fno-elide-constructors
    The C++ standard allows an implementation to omit creating a temporary which 
    is only used to initialize another object of the same type. Specifying this 
    option disables that optimization, and forces G++ to call the copy constructor 
    in all cases.

Standart arasındaki pratikte hiçbir fark yoktur diyor

T a = u;

ve

T a(u);

Eğer T ve U tipi ilkel türleridir. Yani her iki formları kullanabilirsiniz. Ben insanların saniyeden daha ziyade birinci formu kullanın yapar Bu sadece stil olduğunu düşünüyorum.


onlar deklarasyon belirsizliği istiyorum, çünkü bazı insanlar, bazı durumlarda ilk kullanabilir:

T u(v(a));

Bir değişkenin bir tanımı olarak birine bakmak migh ubir türde bir geçici kullanılarak başlatılır vdenilen onun Yapıcı için bir parametre alır a. Ama aslında, hangi derleyici bununla yapar şudur:

T u(v a);

Bu tip bir argüman alır işlevi bildirimi oluşturur v, adlı bir parametre ile a. Yani insanların yaptığı

T u = v(a);

onlar yapmış olabilir rağmen o belirsizliği giderecek

T u((v(a)));

İşlev parametreleri etrafında orada parantez asla çünkü çok, derleyici çok yerine fonksiyon tanımlaması değişken tanımı olarak okurdu :)

Cevap 09/12/2008 saat 19:21
kaynak kullanıcı

oy
4

Eğer performans açısından önemli olduğunu kanıtladın sürece, sizin örnekte atama operatörü kullanılarak fazladan bir kopyasını dert olmaz ( std::string foo = "Foo";). Sana optimize kod bakmak kez bu kopya bile varsa oldukça şaşırırım ben aslında uygun parametreli yapıcı arayacak inanıyoruz.

Sorunuza cevap olarak, evet, bu oldukça yaygın bir âdet olduğunu söyleyebilirim. Klasik, insanlar yerleşik türlerini başlatmak için atama kullanmış ve gelenek değiştirmek için zorlayıcı bir neden yok. Okunabilirlik ve alışkanlık mükemmel nihai koduna sahip ne kadar az darbe verilen bu kongre için geçerli nedenler vardır.

Cevap 09/12/2008 saat 18:59
kaynak kullanıcı

oy
2

Muhtemelen gibi bu kodu bulacaksınız

std::string strFoo = "Foo";

fazladan bir kopyasını yapıyor önlemek ve parantez ile aynı kod (tek argüman yapıcısı bir çağrı) derler olacaktır.

Öte yandan, bir durumlar vardır gerekir böyle bir yapıcı eleman başlatma listesi olarak parantez kullanın.

Yerel değişkenler oluşturmak için = veya parantez kullanımı büyük ölçüde kişisel tercih meselesi olduğunu düşünüyorum.

Cevap 09/12/2008 saat 18:57
kaynak kullanıcı

oy
1

Kim bilir ne onlar düşünüyorum, ama aynı zamanda nesneler değildir, çünkü esas ilkel türleri için = tercih ve onları başlatmak için "olağan" yolu olduğu.

Cevap 09/12/2008 saat 18:58
kaynak kullanıcı

oy
0

Ama sonra sadece daha nesne sözdizimi kullanarak başlatma listesindeki ilkeller başlatmak şaşırtmak için.

foo::foo()   
  ,anInt(0)   
  ,aFloat(0.0)   
{   
}   
Cevap 09/12/2008 saat 19:44
kaynak kullanıcı

oy
0

biri için yapabilir Tek argüman:

std :: string foo ( "bar");

o argümanı, yani değişiklikleri saymak bile şeyin aynı tutar mı:

std :: string foo ( "bar", 5);

Bir '=' işareti ile çalışmaz.

Başka bir şey birçok nesneler için bir '=' örneğin size argüman uzunluğunu veren bir dizi sınıf var ki, doğal olmayan hissediyor olmasıdır:

Dizi dizi = 5;

biz ancak uzunluk 5 ile değer 5 ile bir Array inşa vermediği için, iyi de gelmiyor:

Dizi arr (5);

Eğer sadece bir değer kopyalama, verilen parametre ile bir nesne inşa yılından bu yana, daha doğal geliyor.

Cevap 09/12/2008 saat 19:36
kaynak kullanıcı

oy
0

Bunun bir alışkanlık daha olduğuna inanıyoruz, çok az nesneler = kullanılarak başlatıldı olabilir, dize bunlardan biridir. Ayrıca söylediklerini yapmanın bir yolu "her yerde parantez kullanılarak (dil izin verdiğini Kullanmaya)"

Cevap 09/12/2008 saat 18:59
kaynak kullanıcı

oy
0

Bu tarz bir mesele. "Std :: string = 'Foo olduğunu bile ifadesi', aynı fazladan bir kopyasını içeren çünkü verimsiz olurdu" doğru değil. Bu "ekstra kopyası" derleyici tarafından kaldırılır.

Cevap 09/12/2008 saat 18:57
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more