登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 70|回复: 0

C++基础知识05.指针&引用

[复制链接]

82

主题

2

回帖

107

积分

网站编辑

积分
107
发表于 2025-1-24 09:00:20 | 显示全部楼层 |阅读模式

指针&引用

指针是 C++ 从 C 中继承的重要数据类型,它提供了一种较为直接的地址操作手段,使用指针可灵活实现动态内存的分配。

声明

指针是一种数据类型,具有指针类型的变量称为 <b>指针变量</b>,它用于存放内存地址。在使用指针之前,需对指针进行声明,其一般形式为:

type *pointer_name;

其中 type 表示所指对象的数据类型,即说明所指内存单元存放的数据类型;* 表示声明一个指针类型的变量;pointer_name 表示指针名。

声明三个数据类型不同的指针变量:

int *p; //声明 int 型的指针变量 p。
float *p1; //声明 float 型的指针变量 p1。
char *p2; //声明 char 型的指针变量 p2。

值得注意的是,指针实际存放的是内存地址,不同类型的指针变量用于指向数据类型不同的变量或常量。

C++ 中提供了两个与地址相关的运算符:*& 。其中 * 称为 <b>指针运算符</b>,用于获取指针所指变量的值,例如 *p 表示指针 p 所指变量的值;& 称为 <b>取地址运算符</b>,用于获取一个对象的地址,例如有变量 i,则 &i 表示 i 的存储地址。

#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️⃣在定义指针时为指针赋值:

type *pointer_name=初始地址;

2️⃣在定义指针后为指针赋值:

type *pointer_name;
pointer_name=初始地址;

其中 <b>初始地址</b> 为某个对象的内存地址,一般使用 &对象名 获取。

例如将指针 p 指向变量 po1 的地址,其中变量 po1 的值为 6:

int po1=6; //定义 int 型变量 po1,赋值为 6。
int *p=&po1; //指针变量 p 指向变量 po1 的地址。

其等价于:

int po1=6; //定义 int 型变量 po1,赋值为 6。
int *p; //定义指针变量 p
p=&po1; //指针变量 p 指向变量 po1 的地址。

我们通过一个例子加深一下指针的定义和使用,新建 pointer1.cpp,输入:

#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 的地址。

用指针修改变量所指向内存地址中的数据

#include<iostream>
using namespace std;
int main(){
    int p = 6;
    int *pp = &p;
    *pp = 10;
    cout<<p<<endl; // 10
}

引用

引用是指对已存在的变量别名,我们可以使用引用名来指向对象。

引用与指针主要有三个区别:

  • 可以通过 指针名=0 描述一个空指针,但不存在空引用。
  • 指针可在任何时间进行初始化操作,而引用只能在定义时进行初始化操作。
  • 指针变量指向内存的一个存储单元;而引用只不过是原变量的一个别名而已。

声明引用变量的基本格式为:

type &引用名=被指对象名;

& 在这里是标识作用,而非取地址运算符。

例如定义引用 x,它是整型变量 i 的引用:

int &x=i;

我们通过 <b>初始化时间</b> 来区别一下指针和引用,新建 pointer2.cpp 文件,输入:

#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> 进行的初始化操作。

#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;
}

引用作为返回值

#include <iostream>

using namespace std;

double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};

double& setValues(int i){
  return vals[i];   // 返回第 i 个元素的引用
}

// 要调用上面定义函数的主函数
int main (){

   cout << "改变前的值" << endl;
   for ( int i = 0; i < 5; i++ ){
       cout << "vals[" << i << "] = ";
       cout << vals[i] << 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[i] << endl;
   }
   return 0;
}

当返回一个引用时,要注意被引用的对象不能超出作用域。所以返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。

int& func() {
   int q;
   //! return q; // 在编译时发生错误
   static int x;
   return x;     // 安全,x 在函数作用域外依然是有效的
}

日期&时间

介绍 C/C++ 与时间相关的函数的使用,包括如何获取日历时间,如何获取本地时间,如何将得到的时间格式化输出,如何计算时间间隔,最后面的部分介绍了自定义时间格式的相关语法。

获取时间戳

time_t 是定义在 time.h 中的一个类型,表示一个日历时间,也就是从 1970 年 1 月 1 日 0 时 0 分 0 秒到此时的秒数,原型是:

typedef long time_t; /* time value */

可以看出 time_t 其实是一个长整型,由于长整型能表示的数值有限,因此它能表示的最迟时间是 2038 年 1 月 18 日 19 时 14 分 07 秒。

通过函数 time 获取时间戳

#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 的原型是:

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. [0-60] (1 leap second) */
  int tm_min;           /* Minutes. [0-59] */
  int tm_hour;          /* Hours.   [0-23] */
  int tm_mday;          /* Day.     [1-31] */
  int tm_mon;           /* Month.   [0-11] */
  int tm_year;          /* Year - 1900.  */
  int tm_wday;          /* Day of week. [0-6] */
  int tm_yday;          /* Days in year.[0-365] */
  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 结构表示的时间,函数原型:

struct tm * localtime(const time_t *)

使用 gmtime 获取格林尼治时间,函数原型:

struct tm * gmtime (const time_t *)

使用 localtime 获取当前时间

#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<<"日";
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-2-5 17:56 , Processed in 0.059213 second(s), 28 queries .

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表