C++ 对 C 语言的提高

发布于 2024-06-22 19:29:46 字数 8808 浏览 20 评论 0

命令空间简单使用

引用命令空间的三种方式:

  • 直接指定标识符。例如 std::cout<<"hello"<<std::endl;
    使用 using 关键字。例如 using std::cout;
  • 导入整个命令空间。例如 using namespace std; 导入 std 命名空间;
#include <iostream>

//定义一个命令空间
namespace space1{ 
  int a = 100;
  int b = 200;
}

//using namespace std;
//只导入其中的 cout 和 endl
using std::cout;
using std::endl;

int main(int argc, char const **argv)
{ 
  cout<<"hello"<<endl;
  using namespace space1;//直接导入命令空间
  cout<<a<<" "<<b<<endl;
  return 0;   
}

const 关键字的加强

  • C 语言中的 const 是一个冒牌货,即使用来修饰变量的值不能修改,但是还是可以通过指针指向这个变量,然后修改指针指向的内存来修改这个变量的值;
  • 注意 const#define 的区别: ① #define 只是在预编译时进行字符置换,例如 #define PI 3.14 ,这里的 PI 不是变量,没有类型,不占用存储单元。②而 const float PI = 3. 14 定义了常变量 PI ,它具有变量的属性,有数据类型,占用存储单元,只是在程序运行期间变量的值是固定的,不能改变(真正的不能改变);

测试:

#include <iostream>

int main(int argc, char const **argv)
{
  //a 此时是一个真正的常量 : 不能通过指针修改(C 语言中的 const 是一个冒牌货)
  const int a = 100;
  //如果对一个常量取地址,编译器会临时开辟一个空间 temp,让这个指针指向 temp
  int *p = (int *)&a; //注意要强制转换一下
  *p = 200;
  printf("a = %d, *p = %d\n", a, *p);

  //可以使用 const 定义的"常量"来定义数组(C 语言中不能这样)
  int arr[a]; //ok
  return 0;
}

输出(可以看到 a 没有改变( C 语言中会变)):

a = 100, *p = 200

引用-重点

  • 变量名,本身是一段内存的引用,即别名( alias ). 引用可以看作一个已定义变量的别名;
  • 对变量声明一个引用,并不另外开辟内存单元,例如 int &b = a ,则 ba 都代表同一个内存单元(使用 sizeof()ab 大小是相同的)。引用与被引用的变量有相同的地址;
  • 在声明一个引用时,必须同时初始化(和常量有点类似),即声明它代表哪一个变量;
  • 当声明一个变量的引用后,改引用一直与其代表的变量相联系,不能再作为其他变量的别名。
  • & 符号前有数据类型时,是引用。其他都是代表取地址;
  • 引用所占用的大小跟指针是相等的,引用可能是一个"常指针"( int *const p );
  • 对引用的初始化,可以是一个变量名,也可以是另一个引用。如 int a = 3; int &b = a; int &c = b; 此时,整形变量 a 有两个别名 bc
  • 不能建立 void 类型的引用(但是有 void * 类型指针(万能指针))。不能建立引用的数组(可以有指针数组);

使用经典的 swap 问题来看引用作为形参的简单使用:

#include <stdio.h>

//值传递(不行)
int swap1(int a, int b){ 
  int t = a;
  a = b;
  b = t;
}

//指针(也是值传递)
int swap2(int *a, int *b){   
  int t = *a;
  *a = *b;
  *b = t;
}

//引用(引用传递)
int swap3(int &a, int &b){ 
  int t = a;
  a = b;
  b = t;
}

int main(int argc, char const **argv)
{ 
  int a = 100, b = 200;
  swap1(a, b);
  printf("a = %d, b = %d\n", a , b);
  swap2(&a, &b);
  printf("a = %d, b = %d\n", a , b);
  swap3(a, b);
  printf("a = %d, b = %d\n", a , b);
  return 0;
}

输出:

a = 100, b = 200
a = 200, b = 100
a = 100, b = 200

指针引用

可以建立指针变量的引用,如:

int a = 5;
int *p = &a;
int* &ref = p; //ref 是一个指向 “整形变量的指针变量” 的引用,初始化为 p

下面看一个使用指针引用的例子,对比使用二级指针和使用指针引用的区别:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Student{ 
  int age;
  char name[20];
};

//通过二级指针
void getMem(Student **temp){ 
  Student *p = (Student *)malloc(sizeof(Student));
  p->age = 13;
  strcpy(p->name, "zhangsan");
  *temp = p;
}
//通过引用
void getMem2(Student* &p){ //将 Student*看成一个类型 
  p = (Student *)malloc(sizeof(Student));
  p->age = 14;
  strcpy(p->name, "lisi");
}

//通过指针
void free1(Student **temp){ 
  Student *p = *temp;
  if(p != NULL){ 
    free(p);
    *temp = NULL;
  }
}
//通过指向指针的引用
void free2(Student* &p){ //指向指针的引用
  if(p != NULL){ 
    free(p);
    p = NULL;
  }
}

int main(int argc, char const **argv)
{ 
  Student *p = NULL;
  getMem(&p);
  printf("age = %d, name = %s\n", p->age, p->name); 
  free1(&p);

  printf("------------------\n");

  getMem2(p);
  printf("age = %d, name = %s\n", p->age, p->name);
  free2(p);
  return 0;
}

输出:

age = 13, name = zhangsan
------------------
age = 14, name = lisi

没有引用指针

  • 由于引用不是一种独立的数据类型,所以不能建立指向引用类型的指针变量。
  • 但是,可以将变量的引用的地址赋值给一个指针,此时指针指向的是原来的变量。

例如:

int a = 3;
int &b = a;
int *p = &b;  //指针变量 p 指向变量 a 的引用 b,相当于指向 a,合法

上面代码和下面一行代码相同:

int *p = &a;

输出 *p 的值,就是 b 的值,即 a 的值。
不能定义指向引用类型的指针变量,不能写成:

int& *p = &a; //企图定义指向引用类型的指针变量,错误

const 引用

  • 如果想对一个常量进行引用,必须是一个 const 引用;
  • 可以对一个变量进行 常引用(此时引用不可修改,但是原变量可以修改)。这个特征一般是用在函数形参修饰上,不希望改变原来的实参的值;
  • 可以用常量或表达式对引用进行初始化,但此时必须用 const 作声明(内部是使用一个 temp 临时变量转换);

测试:

#include <stdio.h>
#include <iostream>
using namespace std;

int main(int argc, char const **argv)
{ 
  //对一个常量进行引用
  const int a = 10;
  //int& ref1 = a; //err
  const int &ref1 = a; //ok

  //可以对一个变量进行 常引用(此时引用不可修改,但是原变量可以修改)
  //这个特征一般是用在函数形参修饰上,有时候不希望改变原来的实参的值
  int b = 10;
  const int& ref2 = b;
  //ref2 = 20; //err
  b = 20; // ok
  printf("b = %d, ref2 = %d\n", b, ref2);

  //对表达式做引用
  // 内部系统处理 int temp = c+10; const int& ref3 = temp;
  int c = 30;
  const int& ref3 = c + 10; //合法

  //也可以对不同类型进行转换
  double d = 3.14;
  const int& ref4 = d; // int temp = d; const int& ref4 = temp
  cout<<d<<" "<<ref4<<endl;//b = 3.14,ref4 = 3

  return 0;
}

输出:

b = 20, ref2 = 20
3.14 3

默认参数、函数重载、作用域运算符

  • 如果全局和局部有相同名字变量,使用 :: 运算符来操作全局变量;
    默认参数要注意: 如果默认参数出现,那么右边的都必须有默认参数,也就是只有参数列表后面部分的参数才可以提供默认参数值;
  • 函数重载规则: ①函数名相同。②参数个数不同,参数的类型不同,参数顺序不同,均可构成重载。 ③返回值类型不同则不可以构成重载。
  • 一个函数,不能既作重载,又作默认参数的函数。

简单使用:

#include <stdio.h>

int fun(int a, int b = 20, int c = 30){ 
  return a + b + c;
}

int a = 100;

int main(int argc, char const **argv)
{ 
  // 作用域运算符 ::
  int a = 200;
  printf("a = %d\n", a);
  printf("a2 = %d\n", ::a); //全局的 a

  printf("%d\n",fun(10));
  printf("%d\n",fun(10, 10));
  printf("%d\n",fun(10, 10, 10));
  return 0;
}

newdelete 的使用

  • C 语言中使用 malloc 函数必须指定开辟空间的大小,即 malloc(size) ,且 malloc 函数只能从用户处知道应开辟空间的大小而不知道数据的类型,因此无法使其返回的指针指向具体的数据类型。其返回值一律为 void * ,使用时必须强制转换;
  • C++ 中提供了 newdelete 运算符来替代 mallocfree 函数;
  • 差别: malloc 不会调用类的构造函数,而 new 会调用类的构造函数。② free 不会调用类的析构函数,而 delete 会调用类的析构函数;(析构函数释放的是对象内部的内存,而 delete 释放的是对象,而 delete 也出发析构,所以都可以释放)

例如

new int; //开辟一个存放整数的空间,返回一个指向整形数据的指针
new int(100); //开辟一个存放整数的空间,并指定初始值为 100
new char[10]; // 开辟一个存放字符数组的空间,size = 10
new int[5][4];
float *p = new float(3.14); //将返回的指向实型数据的指针赋给指针变量 p
delete p;
delete []p; //释放对数组空间的操作(加方括号)

简单测试:

#include <stdio.h>

int main(int argc, char const **argv)
{
  // new 和 delete 使用
  int *p1 = new int(10);
  printf("*p1 = %d\n", *p1);
  delete p1;

  int *p2 = new int[10];
  for(int i = 0;i < 10; i++)
    p2[i] = i;
  for(int i = 0;i < 10; i++)
    printf("%d ",p2[i]);
  printf("\n");
  
  delete []p2;
  return 0;
}

输出:

*p1 = 10
0 1 2 3 4 5 6 7 8 9 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

红焚

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文