Toán tử cộng một bậc làm gì? Có một số định nghĩa mà tôi đã tìm thấy ( ở đây và đây ) nhưng tôi vẫn không biết nó sẽ được sử dụng để làm gì. Có vẻ như nó không làm gì cả nhưng đều có lý do của nó, phải không?
Câu trả lời:
Nó sẽ bị quá tải nếu bạn cảm thấy cần thiết; đối với tất cả các loại được xác định trước, nó về cơ bản là không cần chọn.
Việc sử dụng thực tế của toán tử số học một bậc no-op khá hạn chế và có xu hướng liên quan đến hệ quả của việc sử dụng một giá trị trong một biểu thức số học, hơn là chính toán tử. Ví dụ, nó có thể được sử dụng để buộc mở rộng từ các loại tích phân nhỏ hơn int
hoặc đảm bảo rằng kết quả của một biểu thức được coi là một giá trị và do đó không tương thích với một const
tham số không tham chiếu. Tuy nhiên, tôi cho rằng những cách sử dụng này phù hợp hơn với mã chơi gôn hơn là tính dễ đọc. :-)
int
và dẫn đến một giá trị là hiệu ứng của biểu thức -ness, không phải của chính toán tử +.
Trên thực tế, toán tử cộng không làm điều gì đó - ngay cả trong C. Nó thực hiện các chuyển đổi số học thông thường trên các toán hạng và trả về một giá trị mới, có thể là một số nguyên có chiều rộng lớn hơn. Nếu giá trị ban đầu là một số nguyên không dấu có độ rộng nhỏ hơn int
, nó cũng sẽ được thay đổi thành một signed
giá trị.
Thường thì điều này không quan trọng lắm, nhưng nó có thể có ảnh hưởng, vì vậy không nên sử dụng cộng một bậc như một loại "nhận xét" biểu thị rằng một số nguyên dương. Hãy xem xét chương trình C ++ sau:
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);
}
Điều này sẽ hiển thị "x là một số nguyên".
Vì vậy, trong ví dụ này, cộng một lần đã tạo ra một giá trị mới với kiểu và độ có dấu khác.
an integer of greater width
?
Một điều mà trình đơn nguyên tích hợp +
làm là biến lvalue thành rvalue. Ví dụ, bạn có thể làm điều này
int x;
&x;
nhưng bạn không thể làm điều này
&+x;
:)
PS "Quá tải" chắc chắn không phải là câu trả lời đúng. Unary +
được kế thừa từ C và không có quá tải toán tử cấp người dùng trong C.
Điều chính mà unary + đạt được là thăng hạng kiểu thành int cho các kiểu dữ liệu nhỏ hơn int. Điều này có thể khá hữu ích nếu bạn đang cố gắng in dữ liệu char bằng cách sử dụng std::cout
dữ liệu số.
char x = 5;
std::cout << +x << "\n";
rất khác với
char x=5;
std::cout << x << "\n";
Nó cũng có sẵn cho quá tải, nhưng trong thực tế, quá tải của bạn sẽ được gần một NOP.
Nếu bạn cần in giá trị số của các byte thô (ví dụ: các số nhỏ được lưu trữ dưới dạng ký tự) để gỡ lỗi hoặc bất kỳ lý do gì, thì unary + có thể đơn giản hóa mã in. Xem xét
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
Đây chỉ là một ví dụ nhanh. Tôi chắc chắn rằng có những lúc khác khi đơn vị + có thể giúp xử lý các byte của bạn giống số hơn thay vì giống văn bản.
Một mẩu tin lịch sử. Ủy ban tiêu chuẩn hóa C99 cũng cho rằng việc sử dụng hiện tại của cộng một bậc là khá hiếm, bằng chứng là họ đang cân nhắc sử dụng lại nó để đạt được một tính năng khác trong ngôn ngữ: hạn chế đánh giá thời gian dịch của các biểu thức hằng dấu phẩy động. Xem phần trích dẫn sau đây từ Cơ sở lý luận C, phần F.7.4:
Phiên bản đầu tiên của thông số kỹ thuật này cho phép số học hằng số thời gian dịch, nhưng trao quyền cho toán tử một ngôi +, khi được áp dụng cho một toán hạng, để hạn chế đánh giá thời gian dịch của các biểu thức hằng số.
Cuối cùng, ngữ nghĩa đã bị đảo ngược, với đánh giá thời gian chạy được thực thi trong hầu hết các ngữ cảnh (ít nhất là theo quy tắc "như thể") và khả năng thực thi đánh giá thời gian dịch bằng cách sử dụng trình khởi tạo tĩnh. Lưu ý rằng sự khác biệt chính nằm ở việc xuất hiện các ngoại lệ dấu chấm động và các cài đặt độ chính xác hoặc làm tròn dấu chấm động khác, nếu có.
Không nhiều. Lập luận chung cho việc cho phép quá tải operator+()
là chắc chắn có những cách sử dụng trong thế giới thực để quá tải operator-()
và sẽ rất kỳ lạ (hoặc không đối xứng) nếu bạn cho phép quá tải operator-()
nhưng không operator+()
.
Tôi tin rằng lần đầu tiên tôi đọc lập luận này từ Stroustrop, nhưng tôi không có sách bên mình để xác minh nó. Tôi có thể sai.
Unary plus đã có mặt trong C, nơi nó hoàn toàn không làm gì cả (giống như auto
từ khóa). Để không có nó, Stroustrup sẽ phải đưa ra một chất không tương thích vô cớ với C.
Một khi nó ở trong C ++, tự nhiên cho phép một hàm quá tải, giống như hàm trừ một bậc, và Stroustrup có thể đã giới thiệu nó vì lý do đó nếu nó chưa có ở đó.
Vì vậy, nó không có nghĩa là gì. Nó có thể được sử dụng như một loại trang trí để làm cho mọi thứ trông đối xứng hơn, sử dụng +1,5 làm đối diện với -1,5 chẳng hạn. Trong C ++, nó có thể bị quá tải, nhưng sẽ rất khó hiểu nếu operator+()
làm bất cứ điều gì. Hãy nhớ quy tắc tiêu chuẩn: khi nạp chồng các toán tử số học, hãy làm những việc như cách int
làm.
Nếu bạn đang tìm kiếm lý do tại sao nó ở đó, hãy tìm điều gì đó về lịch sử ban đầu của C. Tôi nghi ngờ không có lý do chính đáng, vì C không thực sự được thiết kế. Hãy xem xét auto
từ khóa vô dụng (có lẽ là trái ngược với static
, hiện đang được tái chế trong C ++ 0x) và entry
từ khóa không bao giờ làm bất cứ điều gì (và sau đó bị bỏ qua trong C90). Có một email nổi tiếng, trong đó Ritchie hoặc Kernighan nói rằng, khi họ nhận ra quyền ưu tiên của nhà điều hành có vấn đề, đã có ba bản cài đặt với hàng nghìn dòng mã mà họ không muốn phá vỡ.
entry
: ( stackoverflow.com/q/254395/153285 ). Ngày nay, nếu bạn muốn có nhiều điểm đầu vào, chỉ cần sử dụng lệnh gọi đuôi và tối ưu hóa hướng dẫn hồ sơ.
extern volatile int foo;
, một trình biên dịch đưa ra tuyên bố +foo;
sẽ được yêu cầu thực hiện đọc địa chỉ được chỉ định trên bất kỳ nền tảng nào có thể tồn tại bất kỳ phương tiện nào để xác định rằng quá trình đọc đã diễn ra. Tôi không chắc điều đó sẽ được yêu cầu nếu câu lệnh chỉ là "foo", mặc dù nhiều trình biên dịch sẽ làm điều đó như một phép lịch sự.
Tôi không thể trích dẫn bất kỳ nguồn nào cho điều này, nhưng tôi hiểu rằng nó là để quảng cáo kiểu rõ ràng, ngụ ý chuyển đổi kiểu không mất dữ liệu. Điều đó đặt nó ở đầu hệ thống phân cấp chuyển đổi,
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
new_type operator=(old_type)
Tất nhiên, đó là từ cách giải thích của tôi về một ghi chú trong một trong những sách hướng dẫn c / c ++ của microsoft (thực sự cũ) mà tôi đã đọc khoảng 15 năm trước, vì vậy hãy coi nó như muối bỏ bể.
#include <stdio.h>
int main()
{
unsigned short x = 5;
printf ("%d\n",sizeof(+x));
printf ("%d\n",sizeof(x));
return 0;
}
Như thể hiện trong ví dụ trên, đơn vị + thực sự thay đổi kiểu, kích thước 4 và 2 tương ứng. Kỳ lạ là biểu thức + x thực sự được tính bằng sizeof, tôi nghĩ điều đó không nên. Có lẽ đó là do sizeof có cùng mức độ ưu tiên với dấu +.
Tôi cho rằng bạn có thể sử dụng nó để luôn tạo ra một số dương. Chỉ cần nạp chồng toán tử đơn vị + thành abs. Không thực sự đáng để các nhà phát triển đồng nghiệp của bạn bối rối, trừ khi bạn thực sự chỉ muốn làm xáo trộn mã của mình. Sau đó, nó sẽ hoạt động tốt.
~
gì? Tôi không chắc định nghĩa của bạn về "đối nghịch" là gì, nhưng tôi nghi ngờ nó bị sai lệch theo kinh nghiệm về những gì cộng một và trừ một bậc hiện đang làm.
CHỈNH SỬA Đã viết lại hoàn toàn, bởi vì tôi đã bỏ qua câu trả lời ban đầu của mình.
Điều này sẽ cho phép bạn xử lý khai báo rõ ràng về kiểu của bạn dưới dạng giá trị dương (tôi nghĩ hầu hết là trong các phép toán phi toán học). Có vẻ như phủ định sẽ hữu ích hơn, nhưng tôi đoán đây là một ví dụ về nơi nó có thể tạo ra sự khác biệt:
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; }
}
}
+
không phải để làm cho một giá trị dương, nhưng để giữ nguyên dấu hiệu của nó.
chỉ đơn giản là dùng để thuyết phục những con số nào là tích cực
ví dụ;
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})