Tekli artı operatörü ne yapar?


87

Tekli artı operatörü ne yapar? Bulduğum birkaç tanım var ( burada ve burada ) ama ne için kullanılacağı konusunda hala hiçbir fikrim yok. Hiçbir şey yapmıyor gibi görünüyor ama bunun bir nedeni var, değil mi?


3
Sanırım tarihsel neden ciddi şekilde küçümseniyor.
Wolf

3
Üç farklı dil etiketi olan bir soru oldukça belirsiz / kötüdür! Cevaplar C # (aşırı yüklenebilir) ve C (aşırı yükleme yok) ve C ++ (aşırı yüklenebilir ancak bunu C'den ve dolayısıyla özelliklerini de miras alır) için çok farklıdır.
legends2k

Eric Lippert'in en iyi 10 C # kusuruna bir bağlantı eklemek istiyorum. Tekli artı işlecini onurlu sözlerde bulacaksınız : informit.com/articles/article.aspx?p=2425867 Temel olarak kaldırılması gerektiğini veya hiç eklenmemesi gerektiğini söylüyor.
Noel Widmer

Yanıtlar:


57

İhtiyaç duyarsanız, aşırı yüklenmek için orada; önceden tanımlanmış tüm türler için temelde işlemsizdir.

İşlemsiz tekli aritmetik operatörün pratik kullanımları oldukça sınırlıdır ve operatörün kendisinden ziyade aritmetik ifadede bir değer kullanmanın sonuçlarıyla ilgili olma eğilimindedir. Örneğin, daha küçük integral türlerinden genişletmeye zorlamak intveya bir ifadenin sonucunun bir r değeri olarak değerlendirilmesini ve bu nedenle constreferans olmayan bir parametre ile uyumlu olmamasını sağlamak için kullanılabilir . Bununla birlikte, bu kullanımların golfü kodlamak için okunabilirlikten daha uygun olduğunu bildiriyorum. :-)


7
Aşağıdaki birkaç örnekte gösterildiği gibi bu aslında doğru değil.
jkerian

3
Tamam, bazı kullanımları olduğunu satın alacağım, ancak aşağıda tartışılan kullanımların çoğu, işlemsiz bir operatör kullanılarak oluşturulan sayısal bir ifade olduğu gerçeğiyle ilgilidir: örneğin, intbir r değerine yükseltmek ve bir r değeriyle sonuçlanmak ifadenin etkileridir -ness, + operatörünün kendisi değil.
Jeffrey Hantin

119

Aslında, tekli artı etmez bir şey - bile C. Bu gerçekleştirir zamanki aritmetik dönüşüm işlenen ve döner daha büyük bir genişlikte bir tam sayı olabilir, yeni bir değer. Orijinal değer, işaretsiz tam sayıdan daha küçükse int, bir signeddeğere de değiştirilecektir .

Genellikle bu o kadar önemli değildir, ama olabilir o yüzden, bir etkiye sahip değildir bir tamsayı olumlu olduğunu belirten "comment" bir tür tekli artı kullanmak iyi bir fikirdir. Aşağıdaki C ++ programını düşünün:

void foo(unsigned short x)
{
 std::cout << "x is an unsigned short" << std::endl;
}

void foo(int x)
{
 std::cout << "x is an int" << std::endl;
}

int main()
{
 unsigned short x = 5;
 foo(+x);
}

Bu, "x bir int" gösterecektir.

Yani bu örnekte unary plus, farklı bir tip ve imzalı yeni bir değer yarattı.


5
Bir kısa ve eşit olan bir int verildiğinde verilen sonucu üreten bir kod yazıyorsanız, muhtemelen farklı bir probleminiz vardır
Lie Ryan

1
Teşekkürler, bu durumu açıklığa kavuşturuyor (not: C'de, foo işlevini aşırı yükleyemediğim için çalışacak örneği alamadım)
Binarian

demekle ne anlama geliyor an integer of greater width?
yekanchi

bu bağlamda "genişlik", değerle ilişkili depolama baytlarının sayısını ifade eder.
giles

41

K&R ikinci baskıdan:

Unary +, ANSI standardı ile yenidir. Tekli ile simetri için eklendi -.


6
Kesinlikle. * Bu tarihsel nedendir. C ++ onu uyarlamak zorundaydı, bu yüzden aşırı yükleme ile uğraşmak zorunda kaldı.
Wolf

38

Pozitif değeri negatif bir değerden farklı olarak vurgulamak için netlik için kullanıldığını gördüm:

shift(+1);
shift(-1);

Ama bu oldukça zayıf bir kullanım. Cevap kesinlikle aşırı yüklemedir.


9
Bunu ben de yaptım, özelliklevec3(+1,-1,-1)
mpen

28

Dahili unary'nin +yaptığı bir şey, lvalue'yu bir rvalue'ya dönüştürmektir. Örneğin, bunu yapabilirsiniz

int x;
&x;

ama bunu yapamazsın

&+x;

:)

PS "Aşırı yükleme" kesinlikle doğru cevap değil. Unary +, C'den devralındı ​​ve C'de kullanıcı düzeyinde operatör aşırı yüklemesi yok.


14

Unary + 'nın gerçekleştirdiği en önemli şey, int'ten daha küçük veri türleri için int türüne yükseltmedir. Karakter verilerini std::coutsayısal veriler olarak yazdırmaya çalışıyorsanız, bu oldukça yararlı olabilir .

char x = 5;
std::cout << +x << "\n";

-den çok farklı

char x=5;
std::cout << x << "\n";

Aynı zamanda aşırı yükleme için de mevcuttur, ancak pratikte aşırı yüklemeniz neredeyse NOP olmalıdır .


12

Hata ayıklama veya herhangi bir nedenle ham baytların sayısal değerini (örneğin, karakter olarak depolanan küçük sayılar) yazdırmanız gerekirse, unary + yazdırma kodunu basitleştirebilir. Düşünmek

char c = 42;
cout << c << endl;           // prints "*\n", not what you want in this case
cout << (int)c << endl;      // prints "42\n", ok
cout << +c << endl;          // prints "42\n", much easier to type

Bu sadece hızlı bir örnek. Eminim unary + 'nın baytlarınıza metin yerine sayılar gibi davranılmasına yardımcı olabileceği başka zamanlar da vardır.


4

Tarihsel bir haber. C99 standardizasyon komitesi ayrıca, tekli artı'nın mevcut kullanımlarının, dilde başka bir özellik elde etmek için yeniden kullanmayı düşünmeleriyle kanıtlandığı üzere oldukça nadir olduğunu düşündü: kayan noktalı sabit ifadelerin çeviri zamanı değerlendirmesinin engellenmesi. C Gerekçesi, bölüm F.7.4'ten aşağıdaki alıntıya bakınız:

Bu belirtimin erken bir sürümü, çeviri-zaman sabiti aritmetiğine izin verdi, ancak bir işlenene uygulandığında, sabit ifadelerin çeviri-zamanı değerlendirmesini engellemek için tekli + işlecini güçlendirdi.

Sonunda, çoğu bağlamda uygulanan çalışma zamanı değerlendirmesi (en azından "sanki" kuralı) ve statik başlatıcıların kullanımıyla çeviri zamanı değerlendirmesini uygulama yeteneği ile anlambilim tersine çevrildi. Ana farkın kayan nokta istisnalarının ortaya çıkmasında ve varsa diğer kayan nokta yuvarlama veya hassas ayarlarda yattığını unutmayın.


3

Fazla değil. Aşırı yüklenmesini sağlayan genel argüman operator+()gerçek dünya kullandığı aşırı kesinlikle olmasıdır operator-()ve bu olurdu çok sen aşırı izin olsaydı garip (veya asimetrik) operator-()ancak operator+().

Bu argümanı ilk önce Stroustrop'tan okuduğuma inanıyorum, ancak kitaplarım yanımda bunu doğrulayacak hakkım yok. Yanlış olabilirim.


3

Unary plus, kesinlikle hiçbir şey yapmadığı C de mevcuttu ( autoanahtar kelimeye çok benzer ). Buna sahip olmamak için Stroustrup, C ile gereksiz bir uyumsuzluk getirmek zorunda kalacaktı.

C ++ 'a girdikten sonra, tekli eksi gibi bir aşırı yük fonksiyonuna izin vermek doğaldı ve Stroustrup zaten orada olmasaydı bu nedenle onu tanıtabilirdi.

Yani hiçbir anlamı yok. Eşyaların daha simetrik görünmesini sağlamak için bir tür dekorasyon olarak kullanılabilir, örneğin -1.5'in tersi olarak +1.5 kullanılır. C ++ 'da aşırı yüklenebilir, ancak bir operator+()şey yaparsa kafa karıştırıcı olacaktır . Standart kuralı hatırlayın: Aritmetik operatörleri aşırı yüklerken, ints'nin yaptığı gibi şeyler yapın .

Neden orada olduğuna dair bir neden arıyorsanız, C'nin erken tarihi hakkında bir şeyler bulun. C gerçekten tasarlanmadığı için iyi bir neden olmadığından şüpheleniyorum. Yararsız autoanahtar kelimeyi (muhtemelen static, şimdi C ++ 0x'de geri dönüştürüldüğünün aksine ) ve entryhiçbir şey yapmayan (ve daha sonra C90'da ihmal edilen) anahtar kelimeyi düşünün . Ritchie veya Kernighan'ın, operatör önceliğinin sorunları olduğunu fark ettiklerinde, kırmak istemedikleri binlerce kod satırı içeren üç kurulum olduğunu söylediği ünlü bir e-posta var.


1
Mantıklı olduğunu gördüğüm tek aritmetik olmayan aşırı yükleme, (+ terim) 'in bir veya daha fazla tem anlamına geldiği normal ifadeler veya gramerlerdeydi. (Oldukça standart normal ifade sözdizimi)
Michael Anderson

Hakkında entry: ( stackoverflow.com/q/254395/153285 ). Bu günlerde, birden fazla giriş noktası istiyorsanız, yalnızca kuyruk aramalarını ve profil yönlendirmeli optimizasyonu kullanın.
Potatoswatter

İnanıyorum ki, verilen C99'da bile, ifade verilen extern volatile int foo;bir derleyicinin +foo;, okumanın gerçekleştiğini belirlemek için herhangi bir yolun var olabileceği herhangi bir platformda belirtilen adresi okuması gerekeceğine inanıyorum. İfade sadece "foo" olsaydı bunun gerekli olacağından emin değilim, ancak birçok derleyici bunu bir nezaket olarak yapacak.
supercat

2

Bunun için herhangi bir kaynak belirtemem, ancak bunun kayıpsız tür dönüşümü anlamına gelen açık tür tanıtımı için olduğunu anlamaya başladım. Bu, onu dönüşüm hiyerarşisinin en üstüne yerleştirir,

  • Promosyon: new_type operator+(old_type)
  • Dönüştürmek: new_type(old_type)
  • Oyuncular: operator(new_type)(old_type)
  • Zorlama: new_type operator=(old_type)

Elbette, bu, yaklaşık 15 yıl önce okuduğum microsoft (gerçekten eski) c / c ++ kılavuzlarından birindeki bir nota ilişkin yorumumdan geliyor, bu yüzden onu biraz tuzla alın.


1
#include <stdio.h>
int main()
{
    unsigned short x = 5;
    printf ("%d\n",sizeof(+x)); 
    printf ("%d\n",sizeof(x)); 
    return 0;
}

Yukarıdaki örnekte gösterildiği gibi, tekli + gerçekten sırasıyla tip, boyut 4 ve 2'yi değiştirir. + X ifadesinin gerçekten de sizeof cinsinden hesaplanması tuhaf, bunun olmaması gerektiğini düşündüm. Belki de sizeof'un unary + ile aynı önceliğe sahip olmasından kaynaklanmaktadır.


-1

Sanırım bunu bir sayıyı her zaman pozitif yapmak için kullanabilirsin. Unary + operatörünü abs olması için aşırı yüklemeniz yeterli. Kodunuzu gerçekten karmaşık hale getirmek istemediğiniz sürece, geliştirici arkadaşlarınızın kafasını karıştırmaya değmez. O zaman güzel çalışır.


Bu, tekli eksi negatif abs olmak için aşırı yüklenmedikçe, her türlü matematik
işini

Ahh, evet. Bu yüzden yapmamayı önerdim.
Patrick

1
@ Davy8: Tekli artı şu anda tekli eksi'nin "tersi" olduğunu düşündüren nedir ? Bitsel tümleme operatörünün "tersi" nedir ~? Sizin "zıt" tanımınızın ne olduğundan emin değilim, ancak bunun, tekli artı ve tekli eksi'nin şu anda ne yaptığına dair deneyimlerle önyargılı olduğundan şüpheleniyorum.
ndkrempel

-1

DÜZENLE Tamamen yeniden yazdım, çünkü orijinal cevabımda çok kapalıydım.

Bu, türünüzün açık beyanını pozitif bir değer olarak ele almanıza izin vermelidir (Çoğunlukla matematiksel olmayan işlemlerde düşünüyorum). Görünüşe göre olumsuzlama daha yararlı olacak, ancak sanırım burada bir fark yaratabileceği bir örnek var:

public struct Acceleration
{
    private readonly decimal rate;
    private readonly Vector vector;

    public Acceleration(decimal rate, Vector vector)
    {
        this.vector = vector;
        this.rate = rate;
    }

    public static Acceleration operator +(Acceleration other)
    {
        if (other.Vector.Z >= 0)
        {
            return other;
        }
        return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
    }

    public static Acceleration operator -(Acceleration other)
    {
        if (other.Vector.Z <= 0)
        {
            return other;
        }
        return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
    }

    public decimal Rate
    {
        get { return rate; }
    }

    public Vector Vector
    {
        get { return vector; }
    }
}

Bu bana tekli bir operasyon gibi görünmüyor. İkili olması için iki argüman (nisan ve mayıs) alır.
BlueMonkMN

Bu ikili artı. Tekli artı sadece "+1" veya böyle, sol operand olmadan.
Jeffrey Hantin

benim hatam. CS101'imi unuttum. sabit.
Michael Meadows

3
Üretim kodunda bu tür bir aşırı yükleme bulursam, kesinlikle hata olarak işaretler ve en kısa sürede düzeltirim. 'Nin semantiği +bir değeri pozitif yapmak değil, işaretini değiştirmeden bırakmaktır.
Arturo Torres Sánchez

-1

basitçe hangi sayıların pozitif olduğuna ikna etmek için kullanılan

Örneğin;

int a=10;
System.out.println(+x);// prints 10(that means,that number 10 multiply by +1,{10*+1})

//if we use unary minus

int a=10;
System.out.println(-x);//prints -10(that means,that number 10 multiply by +1,{10*-1})
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.