Tüm C ++ operatörleri bir şey döndürür mü?


83

Çalıştığım tüm C ++ operatörleri bir şey +döndürür, örneğin operatör toplamanın sonucunu döndürür.

Tüm C ++ operatörleri bir şey döndürür mü, yoksa hiçbir şey döndürmeyen bazı C ++ operatörleri var mı?


7
Bu, "operatör" terimini ne kadar dar tanımladığınıza bağlıdır.
molbdnilo

12
Bu, standart tarafından zorunlu kılınmamıştır - örneğin +=, geri dönmek için uygulayabilirsiniz void, ancak bu önerilmez. Ayrıca işlev çağrısı operatörleri geri dönebilir voidve bu geçerlidir
Mircea Ispas

Hmm. Kapsam çözümleme operatörünün ::hiçbir şey döndürmeyeceğine dair bir önsezim var , ancak emin olmak için standarda danışmam gerekiyor.
Yksisarvinen

2
Sorunun bağlamı yalnızca C ++ tarafından sağlanan türler için mi yoksa kullanıcı tanımlı türleri de içeriyor mu?
Eljay

@Eljay Yalnızca C ++ tarafından sağlanan türler.
user8240761

Yanıtlar:


112

Hayır, tüm operatörler bir şey döndürmez.

Muhtemelen tam olarak düşündüğünüz şey olmasalar da , deleteve delete[]C ++ 'anahtar kelimelerinin' aslında operatör olduğunu unutmayın ; ve voiddönüş türüne sahip olarak tanımlanırlar - bu , hiçbir şey olarak değerlendirmedikleri anlamına gelir (bu, 'bir şey' değildir ).

Gönderen cppreference :

void operator delete  ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;

13
Cevabını beğendim, soruyu farklı düşünmemi sağladı. delete, delete[], throw, (void)x;Döküm, sol tarafında, ,bir operatör, sağ taraf ,operatör verimleri bir bu void, bir ?:bir kullanan üçlü throwkollarının biri için, dfri en operator void()(tanımlanmış olur kullanıcı),眠りネロク'in void operator()()(olacaktır kullanıcı tarafından tanımlanır).
Eljay

10
deleteOperatörün nesneyi yok etmesi ve ardından çağırması da kafa karıştırıcı operator delete. Ergo, deleteoperatör ve operator deleteayrı şeyler :( stackoverflow.com/a/8918942/845092
Mooing Duck

7
Silme operatörü hakkında konuşurken neden silme işlevlerinden bahsettiğinizden emin değilim. Fakat herneyse.
Deduplicator

4
@MooingDuck Silme ifadesi nesneyi yok eder ve ardından çağırır operator delete.
NathanOliver

Silme işlemi bir operatör olarak sayılır mı, bir nesnenin geçirilen bir nesneye etki eden bir şey olduğunu düşündüm ?? Silme işleminin çalışması için herhangi bir nesnenin iletilmesine veya oluşturulmasına gerek yoktur ..... Aynı printf gibi .....
Yunfei Chen

82

En tuhaf şeyleri yapmak için özel tür operatörleri aşırı yüklenebilir.

örneğin + operatörü, toplamanın sonucunu döndürür.

Şart değil:

#include <iostream>
struct foo {
    int value = 0;
    void operator+(int x) {
        value += x;
    }
};

int main () {
    foo f;
    f + 3;
}

Burada operator+sol tarafı valueüyeye ekler ve dönüş türü geçersizdir. Bu uydurma bir örnektir, ancak genel olarak, özel bir operatörden bir şey döndürmemek olağandışı değildir.

Aşırı yüklenebilen ve bildiğim bir şeyi iade etme gereksinimi olan tek operatör operator->. Ya ham bir gösterici ya da operator->.


Yeterince tuhaf bir şekilde, aslında aşırı yüklenmiş operatörlerin dönüş değeri üzerinde hiçbir kısıtlama yoktur. Böylece operatörler istediğinizi iade edebilir. en.cppreference.com/w/cpp/language/operators
bracco23

5
@ braccor23 operator->biraz özeldir ve operator->başka istisnalar olup olmadığından emin olmayan bir işaretçi veya nesneye sahip bir nesneyi döndürmesi gerekir
major_prime_is_463035818

1
Evet, tek kısıtlama bu. Karşılaştırma operatörleri için bool bile yok. Bu gerçekten tuhaf görünüyor.
bracco23

9
@ idclev463035818: Belki daha kullanışlı bir örnek İfade Şablonları olabilir. Örneğin, operator*(Matrix const& left, Matrix const& right)dönmeyen bir matris kitaplığı oluşturabilirsiniz , Matrixbunun yerine MatrixMul, eğer daha sonra işleme beslenirse, operator+(Matrix const& left, MatrixMul const& right)önce çarpıp sonra toplamadan daha verimli olan kaynaştırılmış bir çarpma-toplama olabilir.
Matthieu M.

1
@DarrelHoffman G / Ç işlemleri için aşırı yüklendiğinde <<ve >>aşırı yüklendiğinde, akışa geri dönmeleri beklenir, böylece bunları basamaklandırabilirsiniz:stream << foo << bar;
Barmar

34

Nitpick'e göre, operatörler hiçbir şey döndürmez. Bunlar sadece dilde ifadeler yaratmak için kullandığımız sözcüksel öğelerdir. Şimdi, ifadelerin türleri vardır ve değerlere dönüşebilirler ve işleçlerin "şeyleri döndürmek" derken kastettiğin şeyin bu olduğunu varsayıyorum.

Ve evet. Türüne sahip C ++ ifadeleri vardır void(ve sonuç olarak herhangi bir değerle değerlendirilmez). Bazıları açık, bazıları ise daha az. Güzel bir örnek olurdu

throw std::runtime_error()

throwC ++ dilbilgisi altında bir ifadedir. Bunu diğer ifadelerde, örneğin koşullu ifadede kullanabilirsiniz.

return goodStatus() ? getValue() : throw std::runtime_error();

Ve fırlatma ifadesinin türü void. Açıktır ki, bu sadece uygulamanın hızla başka yere gitmesine neden olduğu için, ifadenin değeri yoktur.


21

Yerleşik C ++ operatörlerinden hiçbiri bir şey döndürmez . Aşırı yüklenmiş C ++ operatörleri, operatör gösteriminin bir işlev çağrısı için sözdizimsel bir şeker olduğu ölçüde bir şey döndürür.

Aksine, operatörler tüm değerlendirmek şeye. Bir şeyin türü olduğu kadar iyi tanımlanmış bir değeri de vardır . İşlev çağrısı operatörü bile bir türdür.void operator()(/*params*/)void

Örneğin, platformunuzda kodlanmış değeri olan +'a'bir inttürdür 'a'.

Sorunuz "C ++ operatörlerinin bir voiddönüş türü olabilir mi?" o zaman cevap kesinlikle evettir.


14
@ idclev463035818: Bu , bir sorun yaşadığım geri dönüş terimi . C ++ 'da bir şey döndüren tek şey bir işlevdir. İfadeler bir şey olarak değerlendirilir .
Bathsheba

7
sınıf türlerinin operatörleri, bir şey döndüren yöntemlerdir
large_prime_is_463035818

4
Bu önemli bir noktadır. Özensiz terminoloji kafa karışıklığına yol açar. +1.
Pete Becker

3
@supercat - yorumunuz ben de dahil olmak üzere bir grup çalışkan insana kötülük yapıyor. Standardını yazdı bizler asla mevcut veya geçmiş yoklama diğer derleyiciler tarafından detaylı olarak beklenen derleyici yazarlar dolgusuna. Standardın amacı, C ++ programlama dilinin sözdizimini ve anlambilimini açıkça tanımlamaktı. Evet, sonuç mükemmel değil; En son standartta ele alınan ve önceki sürümlerde ele alınmayan birçok sorun vardır. Bu, o sırada görülmemiş komplikasyonları fark ederek deneyimden gelir.
Pete Becker

3
@ Peter-ReinstateMonica - işte daha güçlü bir sürüm. İfade I++bir değer döndürmez. Türü ikullanıcı tanımlı bir türse, bu ifade olarak uygulanır ve operator++bu, bir değer döndüren bir işlevdir. Siz buna "sözdizimsel şeker" diyorsunuz; Ben buna önemli sonuçları olan bir ayrım diyorum.
Pete Becker

12

Aslında hiçbir şey döndürmeyecek bir işlev çağrısı operatörü tanımlayabilirsiniz . Örneğin:

struct Task {
   void operator()() const;
};

17
Neredeyse herhangi bir operatörü hiçbir şey iade etmeyecek şekilde tanımlayabilirsiniz (ve bu kodu korumak zorunda olacak öfkeli mafyanın
gazabıyla yüzleşebilirsiniz

7
@Yksisarvinen ama en azından bu potansiyel olarak faydalı.
Mark Ransom

11

Operatör void (): kullanıcı tanımlı dönüştürme işlevi için geçersiz

Sen tuhaf tanımlayabilir operator void()derleyici sizi uyarır hatta edecek dönüştürme işlevini, Tiçin voiddönüştürme işlevi asla kullanılmayacaktır :

#include <iostream>

struct Foo {
    operator void() { std::cout << "Foo::operator void()!"; }
    // warning: conversion function converting 'Foo' to 
    //          'void' will never be used
};
    
int main() {
    Foo f;
    (void)f;            // nothing
    f.operator void();  // Foo::operator void()!
}

[class.conv.fct] / 1 tarafından yönetildiği gibi

[...] Bir dönüştürme işlevi, (muhtemelen cv nitelikli) bir nesneyi (muhtemelen cv nitelikli) aynı nesne türüne (veya ona bir başvuruyu) (muhtemelen cv nitelikli) temel sınıfa dönüştürmek için kullanılmaz bu tür (ya da bir referans) ya da hiç (muhtemelen cv nitelikli) void. 117

( 117 ) Bu dönüşümler, aşırı yük çözümü ([over.best.ics], [over.ics.ref]) ve dolayısıyla başlatma ([dcl.init]) ve açık yayınlar için standart dönüşümler olarak kabul edilir. 'A dönüştürme, voidherhangi bir dönüştürme işlevini ([ifade.static.cast]) çağırmaz. Bir dönüştürme gerçekleştirmek için hiçbir zaman doğrudan çağrılmasa bile, bu tür dönüştürme işlevleri bildirilebilir ve potansiyel olarak bir temel sınıftaki bir sanal dönüştürme işlevine yapılan bir çağrı yoluyla erişilebilir.

Bununla birlikte, yukarıda gösterildiği gibi, yine de açık .operator void()sözdizimini kullanarak onu çağırabilirsiniz .


4

Dil tarafından tanımlanan (yerleşik) operatörler, farklı türlerde hesaplamalar gerçekleştirmek için kullanılan simgelerdir:

  • aritmetik (+, -, *, /)
  • artırma / azaltma (++, -)
  • atama (=, + =, - =, * =, / =,% =, >> =, << =, & =, ^ =, | =)
  • mantık (!, &&, ||)
  • ilişkisel (==,! =,>, <,> =, <=)
  • şartlı?
  • virgül

ve bunun gibi. Liste çok kapsamlı olabilir.

Gibi dil kaynaklarda bu bir ya da bu bir , bunlar muhakkak sadece bir aritmetik veya mantık gerçekleştiren bir şey dönen olarak başvurulan değildir operasyonu , bir değişken anlamına gelen bir karşılaştırma değiştirilebilir, vs.

Bu işlem bir değerle sonuçlandığından, operatör tarafından "döndürülmüş" olarak yorumlanabilir, ancak bir işlev dönüş değerinden farklıdır.

Öte yandan aşırı yüklenmiş operatörler, herhangi bir türden bir dönüş değeri ile tanımlanabilir, bu bile geçersiz olabilir, bu nedenle hayır, tüm operatörler C ++ 'da bir değer döndürmez.


3

Dilin sözdizimsel birimi olarak operatörlerden değil, operatör işlevlerinden bahsettiğinizi varsayıyorum.

Operatörleri herhangi bir türde aşırı yüklerseniz, aslında istediğinizi döndürebilirsiniz.

Bu aynı zamanda çok mantıklıdır, çünkü * veya () gibi işlemler bazen çok sezgisel olarak girdi türlerini döndürmeyebilir. Karmaşık bir sayı türünü gerçek sayı türüyle çarptığınızı hayal edin. Veya bir koleksiyondan bir öğe döndüren bir operatör.

Ayrıca, ++ ve - operatörlerini hiçbir şey döndürmemek için aşırı yükleyebilirsiniz, böylece standart sürümün sahip olduğu yan etki ve ifade değerinin son derece hataya açık karışımını ortadan kaldırabilirsiniz .


2

Hayır. Buradaki şu iki örneği düşünün:

int multiply (int a, int b) {
   return a*b;
}

void multiply_void(int a, int b) {
   cout << a*b;
//or cout << multiply(a,b);
}

İlk işlev, başka bir işlev tarafından kullanılabilecek bir tamsayı değeri döndürür. Değer döndürülür ve gerektiğinde kullanılmak üzere bellekte saklanır. Değilse, insan tarafından görülmez ve hafızada mutlu bir şekilde oturur.

İkinci işlev, varsayılan çıkış cihazına (genellikle konsola) çıktı verecektir. Çarpma operatörü tarafından döndürülen değer bir çıktı cihazına aktarılır. Multiply_void işlevi gerçek bir değer döndürmez.


0

Tüm operatörler bir şey döndürür. Operatör olarak adlandırılırlar çünkü bir şeyi çalıştırırlar, bu nedenle bir şey döndürürler. Bir şey döndürmeyen Operatörlere operatör denemez. Duruma bağlı olarak bir değer veya Doğru veya Yanlış döndürürler.


0

Operatörler kendi başlarına herhangi bir şey iade etmezler. İşlev çağrıları değerleri döndürür. Operatörler değerlerle sonuçlanabilir. Operatörler bazen işlevleri çağırabilir. Örnekler şunları içerir:

• İşlev çağrı operatörü.

• Bir işlev çağrısına dönüşen aşırı yüklenmiş bir operatör.

• yeni bir ifadenin parçası olarak çağrılan yeni operatör bir işlev çağrısıdır.

Fonksiyon çağrılarından bahsetmedeki tek amacım, sonuca karşı geri dönüşü açıklığa kavuşturmaktır. 126 "dönüş" örneğinin tamamına ve [ifade] 'de ondan türetilen kelimelere bakıldığında , bölüm şuna atıfta bulunmak için return sözcüğünü dikkatlice kullanıyor gibi görünüyor:

• bir işlev çağrısının sonucu

• eşgüdümlerle ilgili kontrol akışının yönleri

Tamam, bu, sonuç vs geri dönüş konusunda yeterli bilgiçlik.


0

C ++ Operatörlerinin bir şeyi döndürüp döndürmemesi, onları nasıl kullandığınıza bağlıdır. Yerleşik C ++ işleçleri, void döndürmeye zorlanana kadar ve olmadıkça bir değer döndürür.

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.