Apa yang dilakukan operator unary plus?

87

Apa yang dilakukan operator unary plus? Ada beberapa definisi yang saya temukan (di sini dan di sini ) tetapi saya masih tidak tahu untuk apa itu digunakan. Sepertinya tidak melakukan apa-apa tetapi pasti ada alasannya, bukan?

vrish88
sumber
3
Saya pikir alasan historis sangat diremehkan.
Serigala
3
Pertanyaan dengan tiga tag bahasa berbeda cukup ambigu / buruk! Jawabannya sangat berbeda untuk C # (overloadable) dan C (no overloading) dan C ++ (overloadable tetapi mewarisi ini dari C dan karenanya juga propertinya).
legends2k
Saya ingin menambahkan tautan ke 10 kelemahan C # teratas Eric Lippert. Anda akan menemukan operator unary plus di honorable mention: informit.com/articles/article.aspx?p=2425867 Dia pada dasarnya mengatakan itu harus dihapus atau seharusnya tidak pernah ditambahkan.
Noel Widmer

Jawaban:

57

Itu ada untuk dibebani jika Anda merasa perlu; untuk semua tipe standar, ini pada dasarnya tidak ada operasi.

Penggunaan praktis dari operator aritmatika unary no-op cukup terbatas, dan cenderung berhubungan dengan konsekuensi penggunaan nilai dalam ekspresi aritmatika, daripada operator itu sendiri. Misalnya, dapat digunakan untuk memaksa pelebaran dari tipe integral yang lebih kecil ke int, atau memastikan bahwa hasil ekspresi diperlakukan sebagai nilai r dan oleh karena itu tidak kompatibel dengan constparameter non- referensi. Saya menyampaikan, bagaimanapun, bahwa penggunaan ini lebih cocok untuk golf kode daripada keterbacaan. :-)

Jeffrey Hantin
sumber
7
Ini sebenarnya tidak benar, seperti yang ditunjukkan beberapa contoh di bawah ini.
jkerian
3
Oke, saya akan membeli yang memiliki beberapa kegunaan, tetapi sebagian besar penggunaan yang dibahas di bawah berhubungan dengan fakta bahwa itu adalah ekspresi numerik yang dibuat menggunakan operator tanpa operasi: misalnya, mempromosikan ke intdan menghasilkan nilai r adalah efek ekspresi -ness, bukan operator + itu sendiri.
Jeffrey Hantin
119

Sebenarnya, unary ditambah tidak melakukan sesuatu - bahkan dalam C. Ia melakukan konversi aritmatika biasa pada operan dan kembali nilai baru, yang dapat menjadi integer lebar yang lebih besar. Jika nilai asli adalah bilangan bulat unsigned dengan lebar kurang dari int, itu akan diubah menjadi signednilai juga.

Biasanya ini tidak terlalu penting, tetapi dapat berpengaruh, jadi bukan ide yang baik untuk menggunakan unary plus sebagai semacam "komentar" yang menunjukkan bahwa bilangan bulat positif. Pertimbangkan program C ++ berikut:

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);
}

Ini akan menampilkan "x adalah int".

Jadi dalam contoh ini unary plus membuat nilai baru dengan tipe dan tanda tangan yang berbeda .

Charles Salvia
sumber
5
jika Anda menulis kode yang menghasilkan hasil yang diberikan ketika diberi pendek dan int yang sebanding, maka Anda mungkin memiliki masalah yang berbeda
Lie Ryan
1
Terima kasih, itu membuatnya jelas (catatan: Di C, saya tidak bisa mendapatkan contoh untuk bekerja, karena saya tidak bisa membebani fungsi foo)
Binarian
apa yang dimaksud dengan mengatakan an integer of greater width?
yekanchi
dalam konteks ini, "lebar" mengacu pada jumlah byte penyimpanan yang terkait dengan nilai.
giles
41

Dari K&R edisi kedua:

Unary + baru dengan standar ANSI. Itu ditambahkan untuk simetri dengan unary -.

Claudiu
sumber
6
Benar. * Ini adalah alasan historis. C ++ harus menyesuaikannya, jadi harus berurusan dengan kelebihan beban.
Serigala
38

Saya telah melihatnya digunakan untuk kejelasan, untuk menekankan nilai positif yang berbeda dari nilai negatif:

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

Tapi itu penggunaan yang cukup lemah. Jawabannya pasti overload.

bbrown
sumber
9
Saya telah melakukan ini juga, terutama ketika berhadapan dengan vektor sepertivec3(+1,-1,-1)
mpen
28

Satu hal yang +dilakukan unary built-in adalah mengubah lvalue menjadi rvalue. Misalnya, Anda bisa melakukan ini

int x;
&x;

tetapi Anda tidak bisa melakukan ini

&+x;

:)

PS "Overloading" jelas bukan jawaban yang tepat. Unary +diwarisi dari C dan tidak ada operator tingkat pengguna yang kelebihan muatan di C.

Semut
sumber
14

Hal utama yang dicapai unary + adalah promosi tipe ke int untuk tipe data lebih kecil dari int. Ini bisa sangat berguna jika Anda mencoba mencetak data karakter menggunakan std::coutsebagai data numerik.

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

sangat berbeda dari

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

Ini juga tersedia untuk overloading, tetapi dalam praktiknya overload Anda harus mendekati NOP.

jkerian.dll
sumber
12

Jika Anda perlu mencetak nilai numerik byte mentah (misalnya, angka kecil disimpan sebagai char) untuk debug atau alasan apa pun, unary + dapat menyederhanakan kode cetak. Mempertimbangkan

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

Ini hanyalah contoh singkat. Saya yakin ada saat lain unary + dapat membantu memperlakukan byte Anda lebih seperti angka daripada teks.

Nicu Stiurca
sumber
4

Berita menarik sejarah. Komite standardisasi C99 juga menganggap penggunaan unary plus yang ada cukup langka, sebagaimana dibuktikan dengan pertimbangan mereka untuk menggunakannya kembali untuk mencapai fitur lain dalam bahasa: penghambatan evaluasi waktu terjemahan ekspresi konstan floating-point. Lihat kutipan berikut dari C Rationale, bagian F.7.4:

Versi awal spesifikasi ini memungkinkan aritmatika konstan waktu terjemahan, tetapi memberdayakan operator + unary, ketika diterapkan ke operan, untuk menghambat evaluasi waktu terjemahan dari ekspresi konstan.

Pada akhirnya, semantik dibalik, dengan evaluasi waktu berjalan diberlakukan di sebagian besar konteks (setidaknya hingga aturan "seolah-olah"), dan kemampuan untuk menerapkan evaluasi waktu terjemahan dengan menggunakan penginisialisasi statis. Perhatikan bahwa perbedaan utama terletak pada terjadinya pengecualian floating point, dan pengaturan presisi atau pembulatan floating point lainnya, jika ada.

ndkrempel
sumber
3

Tidak banyak. Argumen umum untuk mengizinkan overload operator+()adalah bahwa pasti ada penggunaan dunia nyata untuk overloading operator-(), dan akan sangat aneh (atau asimetris) jika Anda mengizinkan overloading operator-()tetapi tidak operator+().

Saya percaya bahwa saya pertama kali membaca argumen ini dari Stroustrop, tetapi saya tidak memiliki hak untuk memverifikasinya. Saya mungkin salah.

Euro Micelli
sumber
3

Unary plus hadir di C, di mana ia sama sekali tidak melakukan apa-apa (seperti autokata kunci). Untuk tidak memilikinya, Stroustrup harus membuat ketidakcocokan dengan C.

Setelah berada di C ++, wajar untuk mengizinkan fungsi kelebihan beban, seperti unary minus, dan Stroustrup mungkin telah memperkenalkannya karena alasan tersebut jika belum ada.

Jadi, itu tidak ada artinya. Ini bisa digunakan sebagai hiasan untuk membuat sesuatu terlihat lebih simetris, gunakan +1,5 sebagai kebalikan dari -1,5 misalnya. Di C ++, ini bisa kelebihan beban, tetapi akan membingungkan jika operator+()melakukan sesuatu. Ingat aturan standar: saat membebani operator aritmatika, lakukan hal-hal seperti ints do.

Jika Anda mencari alasan mengapa itu ada di sana, temukan sesuatu tentang sejarah awal C. Saya kira tidak ada alasan yang baik, karena C sebenarnya tidak dirancang. Pertimbangkan autokata kunci yang tidak berguna (mungkin berbeda dengan static, sekarang sedang didaur ulang di C ++ 0x), dan entrykata kunci, yang tidak pernah melakukan apa pun (dan kemudian dihilangkan di C90). Ada email terkenal di mana Ritchie atau Kernighan mengatakan bahwa, ketika mereka menyadari bahwa prioritas operator bermasalah, sudah ada tiga instalasi dengan ribuan baris kode yang tidak ingin mereka hancurkan.

David Thornley
sumber
1
Satu-satunya kelebihan non-aritmatika yang saya lihat yang masuk akal adalah dalam ekspresi reguler atau tata bahasa di mana (+ istilah) berarti satu atau lebih tems. (Yang merupakan sintaks ekspresi reguler standar yang cukup)
Michael Anderson
Tentang entry: ( stackoverflow.com/q/254395/153285 ). Saat ini, jika Anda menginginkan banyak titik masuk, cukup gunakan panggilan ekor dan pengoptimalan yang dipandu profil.
Potatoswatter
Saya percaya bahwa bahkan di C99, mengingat extern volatile int foo;, kompiler yang diberikan pernyataan +foo;akan diminta untuk melakukan pembacaan alamat yang ditunjukkan pada platform apa pun di mana cara apa pun mungkin ada untuk menentukan bahwa pembacaan itu terjadi. Saya tidak yakin itu akan diperlukan jika pernyataan itu hanya "foo", meskipun banyak kompiler akan melakukannya sebagai kesopanan.
supercat
2

Saya tidak dapat mengutip sumber apa pun untuk ini, tetapi saya telah memahaminya untuk promosi tipe eksplisit, yang menyiratkan konversi tipe lossless. Itu menempatkannya di bagian atas hierarki konversi,

  • Promosi: new_type operator+(old_type)
  • Konversi: new_type(old_type)
  • Pemeran: operator(new_type)(old_type)
  • Paksaan: new_type operator=(old_type)

Tentu saja, itu dari interpretasi saya tentang sebuah catatan di salah satu manual c / c ++ microsoft (sangat tua) yang saya baca sekitar 15 tahun yang lalu, jadi ambillah dengan sebutir garam.

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

Seperti yang ditunjukkan pada contoh di atas, unary + benar-benar mengubah tipe, ukuran 4 dan 2 masing-masing. Aneh bahwa ekspresi + x memang dihitung dalam ukuran, saya pikir itu tidak seharusnya. Mungkin karena sizeof memiliki prioritas yang sama dengan unary +.

Jose Ladeira
sumber
-1

Saya kira Anda bisa menggunakannya untuk selalu membuat angka positif. Hanya membebani operator + unary menjadi abs. Tidak perlu membingungkan sesama pengembang, kecuali jika Anda benar-benar hanya ingin mengaburkan kode Anda. Maka itu akan bekerja dengan baik.

Patrick
sumber
Itu akan membuatnya bukan kebalikan dari minus unary yang akan membingungkan, kecuali jika Anda juga membebani minus unary menjadi abs negatif, yang akan membuat semua jenis matematika menjadi aneh
Davy8
Uhh, ya. Itu sebabnya saya menyarankan untuk tidak melakukannya.
Patrick
1
@ Davy8: Apa yang membuat Anda berpikir unary plus saat ini adalah "kebalikan" dari unary minus? Apa "kebalikan" dari operator pelengkap bitwise ~? Saya tidak yakin apa definisi Anda tentang "lawan", tetapi saya curiga itu bias oleh pengalaman tentang apa yang saat ini dilakukan oleh unary plus dan unary minus.
ndkrempel
-1

EDIT Tulis ulang sepenuhnya, karena saya tidak menjawab dengan jawaban asli saya.

Ini akan memungkinkan Anda untuk menangani pernyataan eksplisit tipe Anda sebagai nilai positif (saya pikir sebagian besar dalam operasi non-matematika). Tampaknya penyangkalan akan lebih berguna, tetapi saya kira inilah contoh di mana hal itu dapat membuat perbedaan:

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; }
    }
}
Michael Meadows
sumber
Itu tidak terlihat seperti operasi yang tidak biasa bagi saya. Dibutuhkan dua argumen (April dan Mei) sehingga akan menjadi biner.
BlueMonkMN
Itu plus biner. Unary plus hanya "+1" atau semacamnya, tanpa operan kiri.
Jeffrey Hantin
salahku. lupa CS101 saya. tetap.
Michael Meadows
3
Jika saya menemukan kelebihan beban semacam itu dalam kode produksi, saya pasti akan menandainya sebagai bug dan memperbaikinya sesegera mungkin. Semantik +bukan untuk membuat nilai menjadi positif, tetapi membiarkan tandanya tidak berubah.
Arturo Torres Sánchez
-1

sederhana yang digunakan untuk meyakinkan angka mana yang positif

misalnya;

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})
Brazz_Achi
sumber