ตัวดำเนินการ Unary plus ทำอะไร? มีคำจำกัดความหลายอย่างที่ฉันพบ ( ที่นี่และที่นี่ ) แต่ฉันยังไม่รู้ว่าจะใช้ทำอะไร ดูเหมือนว่ามันจะไม่ได้ทำอะไรเลย แต่มันมีเหตุผลใช่มั้ย?
คำตอบ:
จะมีงานล้นมือหากคุณรู้สึกว่าต้องการ สำหรับทุกประเภทที่กำหนดไว้ล่วงหน้าโดยพื้นฐานแล้วจะไม่มีการดำเนินการใด ๆ
การใช้ตัวดำเนินการเลขคณิตยูนารีแบบ no-op ในทางปฏิบัตินั้นค่อนข้าง จำกัด และมีแนวโน้มที่จะเกี่ยวข้องกับผลของการใช้ค่าในนิพจน์ทางคณิตศาสตร์แทนที่จะเป็นตัวดำเนินการเอง ตัวอย่างเช่นสามารถใช้เพื่อบังคับให้ขยับขยายจากประเภทปริพันธ์ที่เล็กกว่าไปint
เป็นหรือตรวจสอบให้แน่ใจว่าผลลัพธ์ของนิพจน์ถือเป็นค่า rvalue ดังนั้นจึงไม่เข้ากันได้กับconst
พารามิเตอร์ที่ไม่อ้างอิง อย่างไรก็ตามฉันขอส่งว่าการใช้งานเหล่านี้เหมาะกับโค้ดกอล์ฟมากกว่าความสามารถในการอ่าน :-)
int
และส่งผลให้ค่า rvalue เป็นผลของการแสดงออก -ness ไม่ใช่ของตัวดำเนินการ + เอง
ที่จริงเอกบวกไม่ทำอะไรสักอย่าง - แม้ในซีดำเนินการแปลงทางคณิตศาสตร์ตามปกติในตัวถูกดำเนินการและส่งกลับค่าใหม่ซึ่งสามารถเป็นจำนวนเต็มของความกว้างมากขึ้น หากค่าเดิมเป็นจำนวนเต็มที่ไม่มีเครื่องหมายซึ่งมีความกว้างน้อยกว่าค่าint
นั้นจะเปลี่ยนเป็นsigned
ค่าเช่นกัน
โดยปกติสิ่งนี้ไม่สำคัญนัก แต่อาจมีผลได้ดังนั้นจึงไม่ควรใช้ยูนารีพลัสเป็น "ความคิดเห็น" ที่แสดงว่าจำนวนเต็มเป็นค่าบวก พิจารณาโปรแกรม C ++ ต่อไปนี้:
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);
}
สิ่งนี้จะแสดง "x คือ int"
ดังนั้นในตัวอย่างนี้ unary plus จึงสร้างค่าใหม่ด้วยประเภทและการลงนามที่แตกต่างกัน
an integer of greater width
อะไร?
จาก K&R ฉบับที่สอง:
unary + เป็นของใหม่ที่มีมาตรฐาน ANSI มันถูกเพิ่มเพื่อความสมมาตรด้วยยูนารี -
ฉันเคยเห็นมันใช้เพื่อความชัดเจนเพื่อเน้นค่าบวกที่แตกต่างจากค่าลบ:
shift(+1);
shift(-1);
แต่นั่นเป็นการใช้งานที่ค่อนข้างอ่อนแอ คำตอบคือเกินกำลังแน่นอน
vec3(+1,-1,-1)
สิ่งหนึ่งที่ unary ในตัว+
ทำคือการเปลี่ยน lvalue เป็น rvalue ตัวอย่างเช่นคุณสามารถทำได้
int x;
&x;
แต่คุณไม่สามารถทำได้
&+x;
:)
ปล. "เกินกำลัง" ไม่ใช่คำตอบที่ถูกต้องแน่นอน Unary +
ได้รับการสืบทอดมาจาก C และไม่มีตัวดำเนินการระดับผู้ใช้ที่โอเวอร์โหลดใน C
สิ่งสำคัญที่ unary + บรรลุคือการเลื่อนประเภทเป็น int สำหรับประเภทข้อมูลที่เล็กกว่า int สิ่งนี้จะมีประโยชน์มากหากคุณพยายามพิมพ์ข้อมูลถ่านโดยใช้std::cout
เป็นข้อมูลตัวเลข
char x = 5;
std::cout << +x << "\n";
แตกต่างจาก
char x=5;
std::cout << x << "\n";
นอกจากนี้ยังมีให้สำหรับการบรรทุกเกินพิกัด แต่ในทางปฏิบัติการโอเวอร์โหลดของคุณควรเกือบจะเป็น NOP
หากคุณจำเป็นต้องพิมพ์ค่าตัวเลขของไบต์ดิบ (เช่นตัวเลขขนาดเล็กที่จัดเก็บเป็นถ่าน) สำหรับการดีบักหรือด้วยเหตุผลใดก็ตาม unary + สามารถทำให้รหัสการพิมพ์ง่ายขึ้น พิจารณา
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
นี่เป็นเพียงตัวอย่างสั้น ๆ ฉันแน่ใจว่ามีบางครั้งที่ unary + สามารถช่วยจัดการไบต์ของคุณให้เหมือนตัวเลขแทนการเหมือนข้อความ
เรื่องน่ารู้ทางประวัติศาสตร์ คณะกรรมการกำหนดมาตรฐาน C99 ยังคิดว่าการใช้ยูนารีพลัสที่มีอยู่นั้นค่อนข้างหายากโดยเห็นได้จากการพิจารณานำกลับมาใช้เพื่อให้ได้คุณสมบัติอื่นในภาษานั่นคือการยับยั้งการประเมินเวลาแปลของนิพจน์คงที่แบบทศนิยม ดูคำพูดต่อไปนี้จาก C Rationale ส่วน F.7.4:
รุ่นแรกของข้อกำหนดนี้อนุญาตให้ใช้เลขคณิตคงที่เวลาแปล แต่เพิ่มขีดความสามารถให้ตัวดำเนินการ unary + เมื่อนำไปใช้กับตัวถูกดำเนินการเพื่อยับยั้งการประเมินเวลาแปลของนิพจน์คงที่
ในท้ายที่สุดความหมายก็กลับรายการโดยมีการบังคับใช้การประเมินรันไทม์ในบริบทส่วนใหญ่ (อย่างน้อยก็ขึ้นอยู่กับกฎ "เสมือน") และความสามารถในการบังคับใช้การประเมินเวลาแปลโดยการใช้ตัวเริ่มต้นแบบคงที่ โปรดทราบว่าความแตกต่างหลักอยู่ที่การเกิดข้อยกเว้นจุดลอยตัวและการตั้งค่าการปัดเศษจุดลอยตัวอื่น ๆ ซึ่งมีอยู่
ไม่มาก. ข้อโต้แย้งทั่วไปสำหรับการอนุญาตให้โอเวอร์โหลดoperator+()
คือมีโลกแห่งความเป็นจริงที่ใช้สำหรับการบรรทุกเกินพิกัดoperator-()
และมันจะแปลกมาก (หรือไม่สมมาตร) ถ้าคุณยอมให้โอเวอร์โหลดoperator-()
แต่ไม่operator+()
แต่ไม่
ฉันเชื่อว่าฉันได้อ่านข้อโต้แย้งนี้จาก Stroustrop เป็นครั้งแรก แต่ฉันไม่มีหนังสือติดตัวไปด้วยเพื่อยืนยัน ฉันอาจจะผิด.
Unary plus มีอยู่ใน C โดยที่มันไม่ได้ทำอะไรเลย (เหมือนกับauto
คีย์เวิร์ด) เพื่อที่จะไม่มีมัน Stroustrup จะต้องแนะนำความเข้ากันไม่ได้กับ C.
เมื่อมันอยู่ใน C ++ มันเป็นเรื่องธรรมดาที่จะอนุญาตให้มีฟังก์ชันโอเวอร์โหลดเช่นเดียวกับยูนารีลบและ Stroustrup อาจแนะนำด้วยเหตุผลนั้นหากยังไม่มี
ดังนั้นมันจึงไม่มีความหมาย สามารถใช้เป็นของตกแต่งเพื่อทำให้สิ่งต่างๆดูสมมาตรยิ่งขึ้นโดยใช้ +1.5 ตรงข้ามกับ -1.5 เป็นต้น ใน C ++ สามารถโอเวอร์โหลดได้ แต่จะสับสนถ้าoperator+()
ทำอะไร จำกฎมาตรฐาน: เมื่อใช้ตัวดำเนินการทางคณิตศาสตร์มากเกินไปให้ทำสิ่งต่างๆเช่นint
ทำ
หากคุณกำลังมองหาเหตุผลว่าทำไมจึงอยู่ที่นั่นให้ค้นหาบางอย่างเกี่ยวกับประวัติในช่วงต้นของ C. ฉันสงสัยว่าไม่มีเหตุผลที่ดีเนื่องจาก C ไม่ได้ออกแบบมาจริงๆ พิจารณาauto
คีย์เวิร์ดที่ไร้ประโยชน์(น่าจะตรงกันข้ามกับstatic
ตอนนี้ถูกรีไซเคิลใน C ++ 0x) และentry
คีย์เวิร์ดซึ่งไม่เคยทำอะไรเลย (และถูกละไว้ใน C90 ในภายหลัง) มีอีเมลชื่อดังที่ Ritchie หรือ Kernighan บอกว่าเมื่อพวกเขาตระหนักว่าลำดับความสำคัญของตัวดำเนินการมีปัญหามีการติดตั้งสามครั้งพร้อมรหัสหลายพันบรรทัดที่พวกเขาไม่ต้องการทำลาย
entry
: ( stackoverflow.com/q/254395/153285 ) ทุกวันนี้หากคุณต้องการจุดเข้าใช้งานหลายจุดเพียงแค่ใช้การโทรหางและการเพิ่มประสิทธิภาพที่แนะนำโปรไฟล์
extern volatile int foo;
คอมไพเลอร์ที่ได้รับคำสั่ง+foo;
จะต้องทำการอ่านที่อยู่ที่ระบุบนแพลตฟอร์มใด ๆ ที่อาจมีวิธีการใด ๆ เพื่อตรวจสอบว่าการอ่านเกิดขึ้น ฉันไม่แน่ใจว่าจำเป็นต้องใช้หากคำสั่งนั้นเป็นเพียง "foo" แม้ว่าคอมไพเลอร์จำนวนมากจะทำเพื่อเป็นการเอื้อเฟื้อ
ฉันไม่สามารถอ้างถึงแหล่งที่มาใด ๆ สำหรับสิ่งนี้ แต่ฉันเข้าใจว่ามันมีไว้สำหรับการโปรโมตประเภทที่ชัดเจนซึ่งหมายถึงการแปลงประเภทที่ไม่สูญเสีย ซึ่งวางไว้ที่ด้านบนสุดของลำดับชั้น Conversion
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
new_type operator=(old_type)
แน่นอนว่านั่นมาจากการตีความโน้ตในคู่มือ c / c ++ ของไมโครซอฟท์ (เก่าจริงๆ) ที่ฉันอ่านเมื่อ 15 ปีที่แล้วดังนั้นจงใช้เกลือสักเม็ด
#include <stdio.h>
int main()
{
unsigned short x = 5;
printf ("%d\n",sizeof(+x));
printf ("%d\n",sizeof(x));
return 0;
}
ดังที่แสดงในตัวอย่างข้างต้นยูนารี + เปลี่ยนประเภทขนาด 4 และ 2 ตามลำดับ แปลกที่นิพจน์ + x คำนวณเป็นขนาดของขนาดฉันคิดว่าไม่ควร บางทีอาจเป็นเพราะ sizeof มีลำดับความสำคัญเท่ากับยูนารี +
ฉันคิดว่าคุณสามารถใช้มันเพื่อสร้างตัวเลขให้เป็นบวกได้เสมอ แค่โอเวอร์โหลดตัวดำเนินการ unary + ให้เป็น abs ไม่คุ้มที่จะสร้างความสับสนให้กับนักพัฒนาเพื่อน ๆ ของคุณเว้นแต่คุณจะต้องการทำให้โค้ดของคุณสับสน จากนั้นมันจะทำงานได้ดี
~
? ฉันไม่แน่ใจว่าคำจำกัดความของคุณ "ตรงข้าม" คืออะไร แต่ฉันสงสัยว่ามันมีอคติจากประสบการณ์ของสิ่งที่ยูนารีบวกและยูนารีลบทำในปัจจุบัน
แก้ไขเขียนซ้ำอย่างสมบูรณ์เพราะฉันรู้สึกแย่กับคำตอบเดิมของฉัน
สิ่งนี้จะช่วยให้คุณสามารถจัดการกับการประกาศประเภทของคุณอย่างชัดเจนเป็นค่าบวก (ฉันคิดว่าส่วนใหญ่ไม่ใช่การดำเนินการทางคณิตศาสตร์) ดูเหมือนว่าการปฏิเสธจะมีประโยชน์มากกว่า แต่ฉันเดาว่านี่คือตัวอย่างที่อาจสร้างความแตกต่าง:
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; }
}
}
+
ไม่ได้ทำให้ค่าเป็นบวก แต่จะปล่อยให้เครื่องหมายของมันไม่เปลี่ยนแปลง
เพียงแค่ใช้เพื่อโน้มน้าวใจว่าตัวเลขใดเป็นค่าบวก
เช่น;
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})