C++基础知识05.指针&引用
# 指针&引用指针是 C++ 从 C 中继承的重要数据类型,它提供了一种较为直接的地址操作手段,使用指针可灵活实现动态内存的分配。
## 声明
指针是一种数据类型,具有指针类型的变量称为 <b>指针变量</b>,它用于存放内存地址。在使用指针之前,需对指针进行声明,其一般形式为:
```c++
type *pointer_name;
```
其中 `type` 表示所指对象的数据类型,即说明所指内存单元存放的数据类型;`*` 表示声明一个指针类型的变量;`pointer_name` 表示指针名。
声明三个数据类型不同的指针变量:
```c++
int *p; //声明 int 型的指针变量 p。
float *p1; //声明 float 型的指针变量 p1。
char *p2; //声明 char 型的指针变量 p2。
```
值得注意的是,指针实际存放的是内存地址,不同类型的指针变量用于指向数据类型不同的变量或常量。
C++ 中提供了两个与地址相关的运算符:`*` 和 `&` 。其中 `*` 称为 <b>指针运算符</b>,用于获取指针所指变量的值,例如 `*p` 表示指针 p 所指变量的值;`&` 称为 <b>取地址运算符</b>,用于获取一个对象的地址,例如有变量 i,则 `&i` 表示 i 的存储地址。
```cpp
#include<iostream>
using namespace std;
int main(){
int *p;
cout<<sizeof(p)<<endl; // 8 计算的是指针变量的大小,64 位系统是 8 字节,32 位系统是 4 字节
cout<<sizeof(*p)<<endl; // 4
char *c;
cout<<sizeof(c)<<endl; // 8
cout<<sizeof(*c)<<endl; // 1
}
```
## 赋值和使用
定义指针后我们仅得到了一个用于存储地址的指针变量,若要确定指针变量存放的内存地址,可以通过给指针赋值实现。其基本形式为:
1️⃣在定义指针时为指针赋值:
```c++
type *pointer_name=初始地址;
```
2️⃣在定义指针后为指针赋值:
```c++
type *pointer_name;
pointer_name=初始地址;
```
其中 <b>初始地址</b> 为某个对象的内存地址,一般使用 `&对象名` 获取。
例如将指针 p 指向变量 po1 的地址,其中变量 po1 的值为 6:
```c++
int po1=6; //定义 int 型变量 po1,赋值为 6。
int *p=&po1; //指针变量 p 指向变量 po1 的地址。
```
其等价于:
```c++
int po1=6; //定义 int 型变量 po1,赋值为 6。
int *p; //定义指针变量 p
p=&po1; //指针变量 p 指向变量 po1 的地址。
```
我们通过一个例子加深一下指针的定义和使用,新建 `pointer1.cpp`,输入:
```c++
#include<iostream>
using namespace std;
int main (){
int po1=6; //定义 int 型变量 po1,赋值为 6。
int *p=&po1; //指针变量 p 指向变量 po1 的地址。
cout << "获取指针所指变量的值: "<<*p<<endl;
cout << "获取指针的内存地址: "<<&p<<endl;
return 0;
}
/**
获取指针所指变量的值: 6
获取指针的内存地址: 0x7fffffffdc10
*/
```
其中 `*p` 运用指针运算符 `*` 获取指针 p 所指变量的值;`&p` 运用取地址运算符 `&` 获取指针 p 的地址。
用指针修改变量所指向内存地址中的数据
```cpp
#include<iostream>
using namespace std;
int main(){
int p = 6;
int *pp = &p;
*pp = 10;
cout<<p<<endl; // 10
}
```
## 引用
引用是指对已存在的变量别名,我们可以使用引用名来指向对象。
引用与指针主要有三个区别:
- 可以通过 `指针名=0` 描述一个空指针,但不存在空引用。
- 指针可在任何时间进行初始化操作,而引用只能在定义时进行初始化操作。
- 指针变量指向内存的一个存储单元;而引用只不过是原变量的一个别名而已。
声明引用变量的基本格式为:
```c++
type &引用名=被指对象名;
```
`&` 在这里是标识作用,而非取地址运算符。
例如定义引用 x,它是整型变量 i 的引用:
```c++
int &x=i;
```
我们通过 <b>初始化时间</b> 来区别一下指针和引用,新建 `pointer2.cpp` 文件,输入:
```c++
#include<iostream>
using namespace std;
int main ()
{
int i=3;
int j=4;
int &x=i; //定义引用 x,它是整型变量 i 的引用。
int *s; //定义指针 s。
s=&j; //指针 s 指向整型变量 j 的地址。
cout << "初始化引用 x: " << x << endl;
cout << "初始化指针 s: " << *s << endl;
return 0;
}
```
其中 `int &x=i;` 表示在 <b>定义引用时</b> 进行的初始化操作。`s=&j;` 表示在 <b>定义指针后</b> 进行的初始化操作。
```cpp
#include<iostream>
using namespace std;
int swap(int &x,int &y){
int tmp = x;
x = y;
y = tmp;
}
int swapByPoint(int *x,int *y){
// *x 是操作内存中的值。
int tmp = *x;
*x = *y;
*y = tmp;
}
int main(){
int x = 10,y = 20;
swap(x,y);
// 20:10 交换成功
cout<<x<<":"<<y<<endl;
int *xp;
int *yp;
xp = &x;
yp = &y;
// 10:20 交换成功
swapByPoint(xp,yp);
cout<<x<<":"<<y<<endl;
}
```
引用作为返回值
```cpp
#include <iostream>
using namespace std;
double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};
double& setValues(int i){
return vals; // 返回第 i 个元素的引用
}
// 要调用上面定义函数的主函数
int main (){
cout << "改变前的值" << endl;
for ( int i = 0; i < 5; i++ ){
cout << "vals[" << i << "] = ";
cout << vals << endl;
}
setValues(1) = 20.23; // 改变第 2 个元素
setValues(3) = 70.8;// 改变第 4 个元素
cout << "改变后的值" << endl;
for ( int i = 0; i < 5; i++ ) {
cout << "vals[" << i << "] = ";
cout << vals << endl;
}
return 0;
}
```
当返回一个引用时,要注意被引用的对象不能超出作用域。所以返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。
```cpp
int& func() {
int q;
//! return q; // 在编译时发生错误
static int x;
return x; // 安全,x 在函数作用域外依然是有效的
}
```
# 日期&时间
介绍 C/C++ 与时间相关的函数的使用,包括如何获取日历时间,如何获取本地时间,如何将得到的时间格式化输出,如何计算时间间隔,最后面的部分介绍了自定义时间格式的相关语法。
## 获取时间戳
time_t 是定义在 time.h 中的一个类型,表示一个日历时间,也就是从 1970 年 1 月 1 日 0 时 0 分 0 秒到此时的秒数,原型是:
```cpp
typedef long time_t; /* time value */
```
可以看出 time_t 其实是一个长整型,由于长整型能表示的数值有限,因此它能表示的最迟时间是 2038 年 1 月 18 日 19 时 14 分 07 秒。
通过函数 time 获取时间戳
```cpp
#include<iostream>
#include<ctime>
using namespace std;
int main(void){
time_t now = time(nullptr);
cout<<now<<endl; // 1667977365
return 0;
}
```
## 获取本地时间
time_t 只是一个长整型,不符合我们的使用习惯,需要转换成本地时间,就要用到 tm 结构,time.h 中结构 tm 的原型是:
```cpp
struct tm {
int tm_sec; // 秒,正常范围从 0 到 59,但允许至 61
int tm_min; // 分,范围从 0 到 59
int tm_hour;// 小时,范围从 0 到 23
int tm_mday;// 一月中的第几天,范围从 1 到 31
int tm_mon; // 月,范围从 0 到 11
int tm_year;// 自 1900 年起的年数
int tm_wday;// 一周中的第几天,范围从 0 到 6,从星期日算起
int tm_yday;// 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
int tm_isdst; // 夏令时
}
// 源码注释
/* ISO C `broken-down time' structure.*/
struct tm{
int tm_sec; /* Seconds. (1 leap second) */
int tm_min; /* Minutes. */
int tm_hour; /* Hours. */
int tm_mday; /* Day. */
int tm_mon; /* Month. */
int tm_year; /* Year - 1900.*/
int tm_wday; /* Day of week. */
int tm_yday; /* Days in year. */
int tm_isdst; /* DST. [-1/0/1]*/
# ifdef __USE_MISC
long int tm_gmtoff; /* Seconds east of UTC.*/
const char *tm_zone; /* Timezone abbreviation.*/
# else
long int __tm_gmtoff; /* Seconds east of UTC.*/
const char *__tm_zone; /* Timezone abbreviation.*/
# endif
};
#endif
```
使用这个结构可以很方便的看到年月日时分秒。
使用 localtime 获取当前系统时间,该函数将 time_t 时间转换为 tm 结构表示的时间,函数原型:
```cpp
struct tm * localtime(const time_t *)
```
使用 gmtime 获取格林尼治时间,函数原型:
```cpp
struct tm * gmtime (const time_t *)
```
使用 localtime 获取当前时间
```cpp
#include<iostream>
#include<ctime>
using namespace std;
int main(){
time_t now = time(nullptr);
cout<<now<<endl; // 1667977365
tm *nowtime = localtime(&now);
cout<<1900+nowtime->tm_year<<"年-";
cout<<1+nowtime->tm_mon<<"月-";
cout<<nowtime->tm_mday<<"日";
}
```
谢谢!!!!!!!!
页:
[1]