数组到指针的隐式转换
- 使用数组对象时,通常情况下会产生数组到指针的隐式转换
#include <iostream>
#include <type_traits>
int main()
{
int a[3] = {1, 2, 3};
std::cout << a[0] << std::endl;
auto b = a; // decay 退化
}
像 decltype(a), sizeof(a) 等情况下,不会发生退化。
- 隐式转换会丢失一部分类型信息
int[3] 类型会包含 3 这个信息,但是 a[4] 会隐式转换为 *(a + 4),造成 3 这个信息丢失。
int main()
{
int a[3] = {1, 2, 3}; // int[3]
std::cout << a[4] << std::endl;
auto b = a; // int*
}
- 可以通过声明引用来避免隐式转换
auto& b = a; // int(&)[3]
- 注意:不要使用 extern 指针来声明数组
合法情况:
source.cpp
int array[4] = {1, 2, 3, 4};
main.cpp
#include <iostream>
extern int array[4];
int main()
{
std::cout << array[1] << std::endl;
}
不合法情况:
source.cpp
#include <iostream>
extern int* array;
int main()
{
std::cout << array[1] << std::endl;
}
运行期错误。
原因:编译期是针对翻译单元来说,因此对于单个文件来说,都是没有问题的。同时,也不是链接错误,因为链接期已经不包含类型信息,只包含符号相关。
运行期 source.cpp 会将 array 的内容当做 地址,即 0x01 00 00 00 02 00 00 00
第二种正确做法:
source.cpp
extern int array[]; // Unknown Bounded Array
-
获得指向数组开头与结尾的指针:
std::(c)begin, std::(c)end -
指针算数:
增加、减少
比较
求距离
解引用
指针索引
int a[3] = {1, 2, 3};
std::cout << a << ' ' << &(a[0]) << ' ' << std::begin(a) << std::endl;
std::cout << a + 3 << ' ' << &(a[3]) << ' ' << std::end(a) << std::endl;
std::cbegin(a) // const int*