C++自修入門實境秀、C++ Primer 5版研讀秀 21/ ~頁144 4.3. Logical and Relational Operat...





value initialization

值的初始化(預設值、預設初始化)

一個類別型別(class type)的物件只有在它的類別具有預設建構子(default constructor)的前提下才會被預設初始化



Used to initialize a container’s elements when a size, but not an element initializer, is specified. Elements are initialized as a copy of this compiler-generated value.

在所指定的是一個大小而非一個元素初始器的時候用來初始化一個容器的元素。元素會被初始化為這個編譯器所產生的值之拷貝。

→對於一個容器(container)而言,值的初始化是就其容器的大小(元素的多少量)來初始化,並不是就其容器的元素來初始化。

25:30 (新第21集)



[]operator ([]運算子)下標運算子

If p is a pointer and n an integer, p[n] is a synonym for *(p+n) .



原第21集毀了,以上時間軸也變成無意義(undefined)了 呵呵

新第21集從此始:

17:00

22:10對一個指標作下標(subscript)其實就是就那個指標位移下標(subscript)值後再解參考(dereference),取出其所在位置的元素

int a[] = {0,1,2,3,4,5};

int* p=a;

int*q= &p[2];

int i = *(p + 2);

if (i==*q)

cout << p[2] << endl;

不是陣列指標也適用,但似乎沒意義:

int a = 0;

int* p=&a;

int*q= &p[2];

int i = *(p + 2);

if (p[2]==*q)

cout << p[2] << endl;

40:00

19:10

|| operator

Logical OR operator. Yields true if either operand is true . The right-hand operand is evaluated only if the left-hand operand is false .

本書似尚未用到這個或運算子!(果然!用英文版搜尋就知道了!「||」這是第一次出現。就不符合他立的「Defined」的標題了。第5版了,都沒人跟他們提?還是第5版才異動的呢?)52:30

42:00

頁133

Chapter 4. Expressions

第4章 運算式

47:00

C++允許我們對內建的運算子套用在類別型別(class type)時,自訂該類別型別(class type)在運用此運算子時能做些什麼操作/運算

51:50

頁134

59:20

4.1. Fundamentals

4.1.1. Basic Concepts

1:1:50

我們有單元運算子(unary operators)和二元運算子(binary operators)。

單元:單一運算元

二元或雙元(成雙成對)

There is also one ternary operator that takes three operands, and one operator, function call, that takes an unlimited number of operands.

There is also one ternary operator that takes three operands, and one operator, There is function call, that takes an unlimited number of operands.

其他還有接受三個運算元的一個三元運算子(ternary operator) ,以及函式呼叫(function call)這個運算子,接受的運算元數沒有限制→

其他還有接受三個運算元的一個三元運算子(ternary operator) ,以及函式呼叫(function call)這個運算子,接受的運算元數是沒有限制的

所以呼叫(調用)函式其實也是運算子的操作



有些符號,如星號(*)是多用途的。既作用在一元運算上,作為單元運算子(unary operators)來用,也作用於二個運算元上,作為二元運算子(binary operators)來用。



⑨對錯問題,回到二作 上下文(前後文)

The context in which a symbol is used determines whether the symbol represents a unary or binary operator. The

不著文字相:

The uses of such symbols are independent; it can be helpful to think of them as two different symbols.

Grouping Operators and Operands

1:22:00

將運算子與運算元群組化

歸組運算子和運算元

歸類分組

1:25:05

Operand Conversions

運算元轉換

頁135

Overloaded Operators

重載的運算子

Because such definitions give an alternative meaning to an existing operator symbol, we refer to them as overloaded operators.

1:37:00

原來所謂的「重載」(多重載入、多載)就是指一個運算子符號具有多重「人格」(意義、作用)嘛

∴ 嚴格來講「overloaded operator」應該是「overloaded operator symbol」

「overloaded operators」

還不如翻成「多重使用的運算子」或「多用途運算子」

多用途不表示可以改變其本性

所謂「江山易改,本性難移」

However, the number of operands and the precedence and the associativity of the operator cannot be changed.

一個運算子符號(symbol)能帶幾個運算元,以及它的優先權與關聯性也不能被改變

associativity 結合性
1:49:00

Lvalues and Rvalues

左值和右值

⑧找對主詞 誰的左右?(暎帶左右〈蘭亭集序〉,那裡的左右是蘭亭的左右→借代「附近」)

這裡的「左、右」是運算子的左或右

Every expression in C++ is either an rvalue (pronounced “are-value”) or an lvalue (pronounced “ell-value”).

在C++中每個運算式不是左值就是右值。(不是R值就是L值)

2:00:00

在C++中,能產生出一個物件或函式的就是lvalue運算式,但是常值物件件卻不能作為這樣運算式的左值(指定assignment的左邊運算元)

Roughly speaking, when we use an object as an rvalue,we use the object’s value (its contents). When we use an object as an lvalue, we use the object’s identity (its location in memory).

大致說來,我們把一個物件當右值(r值)來用時,就是在用它的內容值;而我們把它當作左值(l值)來用時,我們是在用它的記憶體位址。

在VBA中引數有「傳值」「傳址」的不同,想必就是類似這裡的概念。

值,即右值

址,即左值。可以背口令:「左址右值」。

Operators differ as to whether they require lvalue or rvalue operands and as to whether they return lvalues or rvalues.

運算符的不同之處在於它們是否需要左值或右值操作數以及它們是返回左值還是右值。

運算元是左值還是右值,傳回值是左值還是右值,這樣就決定了運算子性質。

2:21:40

運算子 運算元 傳回值

指定(assignment) 左運算元

左值 左值

左運算元

取址(address-of) 左值 指標的右值

內建型別的解參考(dereference)和下標(subscript)

迭代器(iterator)解參考、string、vector 下標 左值

內建型別和迭代器(iterator)++、-- 左值 前綴版本傳回左值

2:35:40

頁136

2:39:20

Lvalues and rvalues also differ when used with decltype (§ 2.5.3 , p. 70 ). When we apply decltype to an expression (other than a variable), the result is a reference type if the expression yields an lvalue.

當套用decltype在運算式上,如果該運算式傳回的是左值(左址右值),那麼decltype評估出來的就會是參考(reference)型別



4.1.2. Precedence and Associativity

2:45:40

4.1.2優先序與結合性

優先權、優先性

2:47:00

複合運算式(compound expression)

就是帶有二個以上的運算子的運算式



複合型別,則是藉另一型別來定義的型別,非合二個以上的型別之意

2:56:10

The arithmetic operators are left associative, which means operators at the same precdence group left to right:

The arithmetic operators are left associative, which means operators at the same precedence group left to right:



算術運算子的結合性(關聯性)是由左到右的,只要是優先權相等,就會先執行左方、前面(群組)的運算,然後才輪到右邊(後面)

3:3:00

Parentheses Override Precedence and Associativity

圓括弧會覆寫(或優遊)任何優先序與結合性的



頁137

3:10:40

When Precedence and Associativity Matter

優先序與結合性的重要性

解參考和指標算術之間的互動(頁120)

3:16:30

難怪ia[4]=p[4],其中的p是int*p=ia;

就是因為我們一旦用到陣列(如此處是ia),那實際上是用到ia第一個元素時指針(即此p)。難怪對一個指標做下標(subscript),就是將其位移下標值的量的意思。

int a[] {2,3,4,5,6,7};

int* p=a;

if (p[2]==a[2])

cout << p[2] << endl;

如上例,印出來是就是「4」。可見對一個指向陣列的指標做下標(subscript),就是對該陣列做下標(或我以前的以為的對一個陣列指定索引值)



3:40:00

表4.12(頁166)

3:42:50

練習4.1

105=5+10*20/2

練習4.2

3:49:30 表4.12

(*(vec.begin()))

(*(vec.begin()))+1



4.1.3. Order of Evaluation

估算的順序

3:59:50

頁138

4:7:00

For operators that do not specify evaluation order, it is an error for an expression to refer to and change the same object. Expressions that do so have undefined behavior(§ 2.1.2, p. 36).

對於沒有指明估算順序的運算子,運算式參考並更改(refer to and change)相同的物件會是 一種錯誤。這麼做的運算式有未定義的行為(§2.1.2)

4:12:10 所以評估(估算)的順序也是很重要,不能模稜兩可曖昧不明、不可測、不確定、不明確的



只有四種運算子的評估(估算)順序是確定的:

There are four operators that do guarantee the order in which operands are evaluated. We saw in § 3.2.3 (p. 94) that the logical AND (&&) operator guarantees that its left-hand operand is evaluated first. Moreover, we are also guaranteed that the right-hand operand is evaluated only if the left-hand operand is true. The only other operators that guarantee the order in which operands are evaluated are the logical OR (||) operator (§ 4.3, p. 141), the conditional (? :) operator (§ 4.7, p. 151), and the

comma (,) operator (§ 4.10, p. 157).

4:22:00

Order of Evaluation, Precedence, and Associativity

估算順序、優先序和結合性

只要不是作用在同一個物件或同一個輸出輸入的行為,那麼運算式的估算順序是不打緊的

也就是說,只要各個運算式的處理對象有交集,那麼若沒有指明或確定的估算順序,則這樣的運算式就是含糊的(未定義的)、一個錯的運算式。

If f, g, h, and j are independent functions that do not affect the state of the same objects or perform IO, then the order in which the functions are called is irrelevant. If any of these functions do affect the same object, then the expression is in error and has undefined behavior.

如果f、g、h與j都是獨立的函式,不會影響到相同物件的狀態或進行IO,

4:32:30

練習4.3

4:36:30

能夠提高效能、優化程式,何樂不為?

陷阱pitfalls只是留給粗心大意的人享用,不是嗎?如果小心翼翼、小心駛得萬年船,又何畏有沒有陷阱呢?



4:39:10

頁139

Advice: Managing Compound Expressions

複合運算式(compound expression)寫作的要領

總之,要有先後順序的,就沒有問題;如果沒有先後順序的,就要注意碰撞、衝突、模稜兩可、不知所措的問題

In this (and similar) expressions, order of evaluation isn’t an issue.

在這個(以及類似的)運算式中,估算的順序並不是問題。

這裡應該是說,估算的順序還是很重要,只不過在這種情況下,其實早就有其內含或預設、默認的估算順序了,所以我們才不必擔心。



The increment (i.e., the subexpression that changes the operand) must be evaluated before the dereference can be evaluated.

遞增 (即改變運算元的子運算式)必在解參考估算之前先被估算。

4.2. Arithmetic Operators

4.2算術運算子

4:57:10

單元的加減運算子較二元的乘法、除法運算子有更高的優先權

算術運算子的運算元與傳回值都是右值rvalue

5:11:00

As described in § 4.11 (p. 159), operands of small integral types are promoted to a larger integral type, and all operands may be converted to a common type as part of evaluating these operators.

§ 4.1.1 (p. 134)也有

5:18:10

頁140

The unary minus operator returns the result of negating a (possibly promoted) copy

of the value of its operand:

int i = 1024;

int k = -i; // i is -1024

bool b = true;

bool b2 = -b; // b2 is true!

int i = 1024;

int k = -i; // i 是-1024

bool b = true;

bool b2 = -b; // b2是 true !

還真看不懂為何是如此!

在Visual Studio i=1024,非-1024,k才是-1024

照這裡下文所述邏輯,則此k應係用來與b2作對照組的,則「// i 是-1024」應係作「// i 是-1024」才是。「i」為「k」的筆誤,中文版亦未訂正。

b2仍是true沒錯

bool b2 = !b

此時b2才會是false

不該對bool值作計算(算術運算)

In § 2.1.1 (p. 34) we noted that bool values should not be used for computation. The result of -b is a good example of what we had in mind.

在§ 2.1.1中我們注意到bool值不應該用於計算。-b的結果就是一個很好的例子。

→-b的結果就是一個值得我們記住的好的例子

Caution: Overflow and Other Arithmetic Exceptions

5:39:24

注意:溢位與其他的算術例外

5:49:50

The value “wrapped around”: The sign bit, which had been 0, was set to 1,resulting in a negative value.

這個值「繞回來(wrapped around)」了 :正負號位元(sign bit)之前是0,現在設為1 了, 結果就是一個負值。

這個值「繞回來(wrapped around)」了 :儲存正負號的位元(sign bit)之前值是0,現在改設為1 了,結果就是一個負值。

電腦都是計0、1 二位元。所以原來記下(儲存)帶minus的號(sign)的那個位元儲存的本來是0(false=無號sign→正數),現在因為溢位(overflow),就改為1(true=有號sign→負數)

6:2:30

頁141

(取)餘數運算子(模數運算子)「%」其運算元一定要是整數型別

%運算子,被稱作「餘數(remainder)」或「模數(modulus)」運算子,

練習4.4

6:28:00

cout<< 12 / 3 * 4 + 5 * 15 + 24 % 4 / 2 <<endl

<< ((((12 / 3) * 4) + (5 * 15)) + ((24 % 4) / 2)) <<endl;

練習4.5

6:34:10

(a) -30 * 3 + 21 / 5

cout<< -30 * 3 + 21 / 5 <<endl

<< -90+4 <<endl;



(b) -30 + 3 * 21 / 5

cout<< -30 + 3 * 21 / 5 <<endl

<< -30+12 <<endl;



(c) 30 / 3 * 21 % 5

cout<< 30 / 3 * 21 % 5 <<endl

<< 0 <<endl;



(d) -30 / 3 * 21 % 4

cout<< -30 / 3 * 21 % 4 <<endl

<< -2 <<endl;

練習4.6

6:38:59

bool isEven(int i) {//判斷是否是偶數

if (i % 2 == 0)

{

return true;

}

else return false;

}

練習4.7

溢位(overflow)

int arr[3];

cout << arr[41] << endl;

陣列下標(subscript)超出索引值上限

short s;

s = 44444;

cout << s << endl;

嚴重性 程式碼 說明

警告 C4309 '=': 轉換導致常數值遭截斷; 可能需要使用較大的類型

4.3. Logical and Relational Operators

6:53:20

0=fasle

其他都是true

邏輯和關係運算子的運算元和傳回值都是右值

頁142

6:57:50

7:3:30

短路估算(short-circuit evaluation)

頁143

7:16:00

It is worth noting that we declared s as a reference to const (§ 2.5.2, p. 69). The elements in text are strings, and might be large. By making s a reference, we avoid copying the elements. Because we don’t need to write to the elements, we made s a reference to const.

原來這裡用參考(reference)是可以增進效能也節省空間。

Logical NOT Operator

7:22:50

The Relational Operators

7:27:20

關係運算子

7:35:40

Equality Tests and the bool Literals 相等性測試和bool字面值

頁144

7:40:00

練習4.8

7:49:40



練習4.9

const char* p{"Hello World"};

if (p&&*p)//只有當p是空指標時才會是0,否則這條件式都能成立

//const char* p{nullptr};

{

cout << p << endl;

}



const char* p{nullptr};

if (p&&*p)//此時p是空指標,這條件式就不成立

{

cout << p << endl;

}

練習4.10

8:6:50

int i;

vector<int>ivec;

while (cin>>i && i!=42 )

{

ivec.push_back(i);

}

for (int v : ivec)

cout << v << " ";

cout << endl;

練習4.11

8:12:30

int a=21, b=14, c=3, d=1;

if (a>b && b>c && c>d)

{

cout << "OK" << endl;

}

練習4.12

int i=1, j=4, k=8;

if(i != j < k)//j<k先比,傳回true true再和i比,則轉為int=1,所以只有i=1時,此條件才不成立

cout << (i != (j < k)) << endl;

4.4. Assignment Operators

留言

熱門文章