Re: [問題] 多載運算子的問題
※ 引述《cplusplus (永夜)》之銘言:
: ※ 引述《LPH66 (運命のルーレット廻して)》之銘言:
: : 這表示前置++ 它是可以做為左值的(雖然好像沒什麼意義)
: : 因此要回傳其參考
: 其實這是蠻有爭議性的,這邊只是因為前置++的特性是先運算完再傳回運算完的值
: 所以可以傳回物件本身,不過語意上來講,應該是要傳回他的值(r-value)
: 就是 Object, 但是位了效率避免copy,就傳回參考 Object&
: 但是傳回的"東西"又不該代表原本的物件本身以防被修改(r-value)
: 所以也有很多是採用 const Object&
: 因此傳回Object &有爭議,必須要看看你的OBJECT的特性來決定
: 如果像是表示value的class,最好可以遵循一般大眾的認知
: 因為像是 ++(++a) 這樣用上面的方式可行,但是概念上不與primitive type的行為不符
: 所以這有可討論的空間
: ps ++++a 在有的compiler可行 有的就不行 盡量別用吧
這裡是 C 和 C++ 不同的地方。assignment operation (包括
=, +=, -=, ...,還有這裡所討論的 prefix ++) 其傳回值,
在 C 是 rvalue, 而 C++ 是 lvalue. 對 C++ 來說,prefix ++
expression 是 lvalue, 而 postfix ++ 才和 C 一樣,是 rvalue.
C++ 的 prefix ++ 以及其他的 assignment expression 是 lvalue
有什麼用處呢?可以用在函式的 call-by-reference 和 return by reference.
(顯然這是 C 所沒有的),如:
void f(int& n) { if (n == 1) n = 2; }
//...
int i = 0;
f(++i); // i 先加1,然後以 lvalue 做為引數,呼叫完函式 i 就會變成 2
cout << i << endl; // 印出 2
int& g(int n = 0) { static int i = 0; return i += n; }
//...
cout << g(1) << endl; // 印出 1
g() += 2; // 可以從外面改變 g() 中 static int i 的值
cout << g() << endl; // 印出 3
以上是針對內建型別和內建 operator。至於 UDT(user-defined type) 和
user-defined overloaded operator 當然可以自己高興要傳回 rvalue 或
lvalue, 只是為了給使用者最小的意外,最好能仿照內建 operator 的行為,
以維持統一的程式風格。這樣一來,像是 function template 也能同時吃
內建型別和 UDT 做為其 reference-type argument 而不會發生不一致的情形:
template <typename T>
void foo(T& a) { /* ... */ }
//...
int x = 0;
foo(++x);
class C { /* 有定義 C& operator++(); */ };
C c;
foo(++c);
至於 int a = 0; ++++a; 這種寫法,由於對 C 來說 ++a 是 rvalue
所以就不能在 rvalue 上再做 ++ 的動作,於是 ++++a 用 C compiler
來編,就不能通過(ill-formed)。但是 C++ 的話,由於 ++a 是 lvalue,
所以再做一次 ++ 的話,是可以通過編譯。只是 C++ 和 C 一樣,另外
有一條重要的規定,就是在一個 expression 中,不能對同一個 scalar
object(不妨理解成原始型別的變數)所存的值修改超過一次以上。否則
結果就是 undefined behavior.
undefined behavior 是很討厭的東西,標準並不要求編譯器一定
要對此發出任何警告或錯誤訊息,但是若編譯器編出的碼執行出
任何可怕的後果(包括引爆核彈),仍然不算違反標準。所以寫程式
的人自己要非常小心,即使能編,一時也能執行出某種好的結果,
只要標準說是 undefined behavior 的寫法就絕對不要去碰。
(以前討論過的 cout << i << ++i; 也是這一類)
所以 ++++a 雖然可通過 C++ 的編譯,但不應該這麼寫。
再來看 user-defined postfix operator++ 依照上述的理由,
固然也該和 built-in postfix ++ 一樣,傳回 rvalue, 但這
個 rvalue (假設 type 是 T) 究竟該用 T 就好,還是 const T。
像 Scott Meyers 和 Herb Sutter 都是用 const T, 不過也有
專家認為該用 T. 這個有機會再來討論 :-)
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
推
61.59.30.19 06/24, , 1F
61.59.30.19 06/24, 1F
推
140.115.205.46 06/24, , 2F
140.115.205.46 06/24, 2F
推
140.115.205.46 06/24, , 3F
140.115.205.46 06/24, 3F
推
218.160.84.199 06/24, , 4F
218.160.84.199 06/24, 4F
推
218.163.120.36 06/25, , 5F
218.163.120.36 06/25, 5F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章
-4
30