C++自修入門實境秀、C++ Primer 5版研讀秀 19/ 陣列與指標之算術操作~3.5.4. C-Style Character Stri...
Pointers Are Iterators 指標是迭代器(iterator)
In particular, pointers to array elements support the same operations as iterators on vector s or string s (§ 3.4 , p. 106 ).
迭代器(iterator)能做的,指標指針也能做
3:00
就跟指標一樣,我們可以對一個迭代器進行解參考(dereference)來取得一個迭代器所代表 的元素。此外,就像指標,我們能夠解參考的,只有代表了一個元素的有效迭代器(§2.3.2)。 解參考一個無效的迭代器或off-the-end迭代器會有未定義的行為。(頁107)
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *p = arr; // p points to the first element in arr
++p; // p points to arr[1]
用陣列給一個指標初始化,就是將陣列的第一個元素的位址(address)給該指標當作初始值
Just as we can use iterators to traverse the elements in a vector , we can use pointers to traverse the elements in an array.
可見traverse和迭代(iterate)仍然是一個意思
9:10
12:00
We can obtain an off-the-end pointer by using another special property of arrays.
前面有尾端後迭代器(off-the-end iterator),這裡是尾端後指標指針(off-the-end pointer)
陣列的性質(property)還真多,還special的咧!
We can obtain an off-the-end pointer by using another special property of arrays. We can take the address of the nonexistent element one past the last element of an array:
Click here to view code image
int *e = &arr[10]; // pointer just past the last element in arr
16:00 難怪,我們當初在測試練習3.30時超出一個索引值竟然沒有錯誤出現,要出迴圈後,Visual Studio才會顯示錯誤!原來就是因為指標可以指向一個尾端後的「不存在的元素」
Exercise 3.30: Identify the indexing errors in the following code:
Click here to view code image
constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
ia[ix] = ix;
int ia[] = { 0,1,2,3,4,5, 6,7,8,9 };
auto *pia(ia);
auto* piae(&ia[10]);
for (auto pia(ia) ; pia !=piae; ++pia)
{
cout << *pia << " ";
}
cout << endl;
auto很像C#中的var
33:00
27:40
The Library begin and end Functions
34:10為了要更方便且安全地使用指標指針(pointer),新的C++標準程式庫納入了兩個begin與end函式
這兩個函式的行為能力和容器中的begin、end兩個成員函式是一樣的
However, arrays are not class types, so these functions are not member functions.
因為陣列不是類別型別,所以這兩個函式並不算是成員函式。
陣列不是類別型別而是一種資料結構
三種:
1.資料結構 array struct
2.類別型別(class type) struct
3.模板型別(template type) vector
和容器的begin、end不帶引數不同,程式庫的這兩個函式是要帶一個陣列作引數
看要取得哪個陣列的begin 和 end 就傳那個陣列作引數給begin和end這兩個函式
頁119
53:00
These functions are defined in the iterator header.
可見要用此二函式,得#include<iterator>先才行
然而我們這樣寫也沒用,反而要像下列黃色塊處:
#include <iostream>
//#include<iterator>
using namespace std;
//using std::cout; using std::cin;using std::endl;
void test() {
int ia[] = { 0,1,2,3,4,5, 6,7,8,9 };
auto *pia(begin(ia));
auto* piae(end(ia));
for (pia ; pia !=piae; ++pia)
{
cout << *pia << " ";
}
cout << endl;
}
note
1:11:50
Pointer Arithmetic
1:13:50
address 定址
1:27:00
頁120
1:29:35
auto n = end (arr) - begin (arr); // n 為 5,即 arr 中元素的數目
1:38:00
The result of subtracting two pointers is a library type named ptrdiff_t. Like size_t, the ptrdiff_t type is a machine-specific type and is defined in the cstddef header.
機器特定型別(machine-specific type)
cstddef ①斷句
c.std.def 1:44:30
typedef int ptrdiff_t;
ptrdiff_t也不過是int的別名
std::ptrdiff_t is the signed integer type of the result of subtracting two pointers. https://en.cppreference.com/w/cpp/types/ptrdiff_t
1:50:00 對陣列指針作關係運算
2:53:00 對二個不相干的指標作關係運算是沒有意義的
2:59:00 非陣列指標要做算術運算也應該是指向同一個非陣列物件(或那個物件後的一個位置)的數個指標來故計算,而不是指向不同物件的指標來做運算。對指向不同物件的指標做的運算,就是上述的不相干、無意義的。
3:5:20
Interaction between Dereference and Pointer Arithmetic
3:11:00
int arr[] = { 0,1,2,3,4,15 };
int last = *(arr + 5);
直接對arr做運算,即是對arr的第一個元素的指標做運算:
As we’ve seen, in most places when we use the name of an array, we are really using a pointer to the first element in that array.
(arr + 5)結果型別是指標int*
所以對一個陣列的解參考(dereference),也就是對它第一個元素的指標作解參考,其結果就是該元素的值。
last = *ia + 4; // ok:last = 4,等同於 ia[0] + 4
頁121
3:19:55
Subscripts and Pointers
int i = ia[2]; // ia is converted to a pointer to the first element in ia
// ia[2] fetches the element to which (ia + 2) points
所以陣列名一出現的地方,實際上編譯器是先將該陣列轉成對該陣列第一元素的指標,然後再對其進行運算;在做下標(subscript)運算時,當然也是如此。因此,諸如ia[2],這樣的表示,在編譯器看來就是先將ia轉成對ia第一元素的指標,然後再對此指標進行下標(指定它往後移動2個位置)
3:32:00
只要一個指標是一個有效的指向某個陣列元素的指標,就可以對該指標做下標(subscript)運算,對它的下標運算,就好像對該陣列做下標一樣,因為對一個陣列做運算實際上就是對該陣列的第一元素做運算也。
下標在此的意義就是對該指標進行位移的指定。
3:41:20
程式庫型別(library type)vector string 下標值不可能是負的,但陣列(其元素之指標下標值)卻可以
The library types force the index used with a subscript to be an unsigned value.
3:42:59
練習3.34
int arr[] = { 0,1,2,3,4,15 };
int* p1;
int* p2;
for (size_t i = 0; i < 7; i++)// 7=sizeof(arr) / sizeof(*arr)+1
{
p1=&arr[i];
for (size_t j = 0; j < 7; j++)
{
p2= &arr[j] ;
p1 += p2 - p1;// is equivalent to
//p1=p1+(p2-p1);
/*兩個指標相減就是ptrdiff_t型別的位移值
而這個位移值是再加到p1本身去的*/
cout << *p1 << endl;
}
}
//int* p1{ &arr[2] }, * p2{&arr[2]};
if (p1!=p2)
{
p1 = p2;
}
最後結果p1都是等於p2,且沒有不合法的結果,只要p1、p2給定的值都是合法的
練習3.35
4:37:58
int arr[] = { 0,1,2,3,4,15 };
int* p = arr, * e{end(arr)};
for (auto i : arr)
cout << i << " ";
cout << endl;
while (p<e)
{
*p = 0;
++p ;
}
for (auto i : arr)
cout << i << " ";
cout << endl;
練習3.36
4:45:40
int arr[] = { 0,1,2,3,4,15 };
int arr1[] = { 0,1,2,3,4,15 };
size_t sz = sizeof(arr) / sizeof(*arr);
for (size_t i = 0; i <sz ;++i){
if (arr[i]!=arr1[i])
{
return;
}
}
cout << "arr and arr1 are equal" << endl;
改寫成vector的: 4:53:52
vector<int> arr{ 0,11,2,3,4,15 };
vector<int> arr1{ 0,11,2,3,4,15 };
size_t sz = arr.size();
for (size_t i = 0; i <sz ;++i){
if (arr[i]!=arr1[i])
{
cout << "arr and arr1 are NOT equal" << endl;
return;
}
}
cout << "arr and arr1 are equal" << endl;
頁122
3.5.4. C-Style Character Strings
留言