200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > C++ 学习(基础语法篇)

C++ 学习(基础语法篇)

时间:2019-06-11 23:20:59

相关推荐

C++ 学习(基础语法篇)

一、基础语法

1.1 C++ 简介

C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。C++ 是 C 的一个超集,事实上,任何合法的 C 程序都是合法的 C++ 程序。使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。

面向对象程序设计

完全支持面向对象的程序设计,包括面向对象开发的四大特性:封装、抽象、继承、多态。

标准库

核心语言,提供了所有构件块,包括变量、数据类型和常量,等等。C++ 标准库,提供了大量的函数,用于操作文件、字符串等。标准模板库(STL),提供了大量的方法,用于操作数据结构等。

ANSI 标准

所有的C++编译器制造商均支持ANSI 标准,能够保证其便携性(代码在Mac、UNIX、Windows、Alpha 计算机上都能通过编译)。

1.2 C++ 环境设置

文本编辑器

编译器

写在源文件中的源代码是人类可读的源。它需要"编译",转为机器语言,这样 CPU 可以按给定指令执行程序。大多数的 C++ 编译器并不在乎源文件的扩展名,但是如果您未指定扩展名,则默认使用 .cpp。常用的免费可用的编译器是 GNU 的 C/C++ 编译器

1.3 C++ 基本语法

C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。

对象- 对象具有状态和行为,对象是类的实例。- 类可以定义为描述对象行为/状态的 模板/蓝图。方法- 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。即时变量- 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。

C++ 程序结构

Eg:输出“Hello World”

#include <iostream>using namespace std;// main() 是程序开始执行的地方int main(){cout << "Hello World"; // 输出 Hello Worldreturn 0;}

using namespace std;告诉编译器使用 std 命名空间。

编译&执行 C++ 程序

上述代码保存为“hello.cpp”,打开所在路径,输出“Hello World”

$ g++ hello.cpp$ ./a.out

C++ 中的分号 & 语句块

在 C++ 中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。语句块是一组使用大括号括起来的按逻辑连接的语句。

1.4 C++ 注释

/*开始*/结束(多行)//单行

1.5 C++ 数据类型

基本内置类型

typedef 声明

可以使用 typedef 为一个已有的类型取一个新的名字。typedef type newname;

枚举类型

枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。关键字 enum

enum 枚举名{ 标识符[=整型常数], 标识符[=整型常数], ... 标识符[=整型常数]} 枚举变量;

如果枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始。例如,下面的代码定义了一个颜色枚举,变量 c 的类型为 color。最后,c 被赋值为 “blue”。

enum color { red, green, blue } c;c = blue;

默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。但是,您也可以给名称赋予一个特殊的值,只需要添加一个初始值即可。例如,在下面的枚举中,green 的值为 5。blue 的值为 6,因为默认情况下,每个名称都会比它前面一个名称大 1,但 red 的值依然为 0。

enum color { red, green=5, blue };

1.6 C++ 变量类型

大写字母和小写字母是不同的,因为 C++ 是大小写敏感的。

C++ 中的变量声明

使用extern声明变量,使用多个文件且只在其中一个文件中定义变量。变量可以声明多次,但只能定义一次。extern作用:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。在文件t2.cpp中有代码:

int x = 10;

在文件t1.cpp中有代码:

#include <iostream>using namespace std;extern int x;int main() {cout << x;return 0;}

输出:10

extern表示声明一个变量,声明使得这个名字为程序所指,而定义创建了和这个名字相关联的实体。

如:

int x = 10;

则是定义一个变量。

声明和定义分开,这样的意义就是可以在一个文件中使用另一个文件的变量,如上面的t1.cpp使用t2.cpp的变量。

C++ 中的左值(Lvalues)和右值(Rvalues)

左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。变量是左值,数值型的数字是右值(Eg:10)

1.7 C++ 变量作用域

作用域是程序的一个区域,一般来说有三个地方可以定义变量: 在函数或一个代码块内部声明的变量,称为局部变量。在函数参数的定义中声明的变量,称为形式参数。在所有函数外部声明的变量,称为全局变量。 在程序中,局部变量和全局变量的名称可以相同,但是在函数内,局部变量的值会覆盖全局变量的值。初始化局部变量和全局变量 当局部变量被定义时,系统不会对其初始化,必须自行对其初始化。定义全局变量时,系统会自动初始化为下列值:

|数据类型| 初始化默认值|

|-----|-----|

|int| 0|

|char| ‘\0’|

|float |0|

|double |0|

|pointer |NULL|

1.8 C++ 常量

常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量可以是任何的基本数据类型,可分为整型数字、浮点数字、字符、字符串和布尔值。常量就像是常规的变量,只不过常量的值在定义后不能进行修改。整数常量: 可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)

定义常量

使用 #define 预处理器。

#define identifier value// eg:#define LENGTH 10

使用 const 关键字。

const type variable = value;// eg:const int LENGTH = 10;

二者区别:

用const的优点:会进行类型安全检查。而define没有安全检查,且可能会产生意料不到的错误。

1.9 C++ 修饰符类型

C++ 允许在 char、int 和 double 数据类型前放置修饰符。数据类型修饰符:signed、unsigned、long、short修饰符 signed、unsigned、long 和 short 可应用于整型,signed 和 unsigned 可应用于字符型,long 可应用于双精度型。修饰符 signed 和 unsigned 也可以作为 long 或 short 修饰符的前缀。例如:unsigned long int。

类型限定符

volatile作用:

volatile关键字是防止在共享的空间发生读取的错误。只保证其可见性,不保证原子性;使用volatile指每次从内存中读取数据,而不是从编译器优化后的缓存中读取数据,简单来讲就是防止编译器优化。

1.10 C++ 存储类

存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前。 autoregisterstaticexternmutablethread_local (C++11)从 C++ 11 开始,auto 关键字不再是 C++ 存储类说明符,且 register 关键字被弃用。

auto

自 C++ 11 以来,auto 关键字用于两种情况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。

register

register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)Eg:register int miles;寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 ‘register’ 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

static

static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。(局部静态变量不销毁)static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。

#include <iostream>// 函数声明 void func(void);static int count = 10; /* 全局变量 */int main(){while(count--){func();}return 0;}// 函数定义void func( void ){static int i = 5; // 局部静态变量i++;std::cout << "变量 i 为 " << i ;std::cout << " , 变量 count 为 " << count << std::endl;}

结果:

变量 i 为 6 , 变量 count 为 9变量 i 为 7 , 变量 count 为 8变量 i 为 8 , 变量 count 为 7变量 i 为 9 , 变量 count 为 6变量 i 为 10 , 变量 count 为 5变量 i 为 11 , 变量 count 为 4变量 i 为 12 , 变量 count 为 3变量 i 为 13 , 变量 count 为 2变量 i 为 14 , 变量 count 为 1变量 i 为 15 , 变量 count 为 0

extern

extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。extern 是用来在另一个文件中声明一个全局变量或函数,通常用于当有两个或多个文件共享相同的全局变量或函数。

mutable

允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。

thread_local

使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。可以将 thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。

thread_local int x; // 命名空间下的全局变量class X{static thread_local std::string s; // 类的static成员变量};static thread_local std::string X::s; // X::s 是需要定义的void foo(){thread_local std::vector<int> v; // 本地变量}

thread_local变量是C++ 11新引入的一种存储类型。它会影响变量的存储周期(Storage duration),C++中有4种存储周期

automaticstaticdynamicthread

有且只有thread_local关键字修饰的变量具有线程周期(thread duration),这些变量(或者说对象)在线程开始的时候被生成(allocated),在线程结束的时候被销毁(deallocated)。并且每 一个线程都拥有一个独立的变量实例(Each thread has its own instance of the object)。

thread_local可以和staticextern关键字联合使用,这将影响变量的链接属性(to adjust linkage)。

适用范围:

命名空间下的全局变量类的static成员变量本地变量

既然每个线程都拥有一份独立的thread_local变量,那么就有2个问题需要考虑:

各线程的thread_local变量是如何初始化的? 每个线程都会进行一次单独初始化各线程的thread_local变量在初始化之后拥有怎样的生命周期,特别是被声明为thread_local的本地变量(local variables)? 声明为thread_local的本地变量在线程中是持续存在的,不同于普通临时变量的生命周期,它具有static变量一样的初始化特征和生命周期

1.11 C++ 运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号 算术运算符关系运算符逻辑运算符位运算符赋值运算符杂项运算符

算数运算符

关系运算符

逻辑运算符

位运算符

赋值运算符

杂项运算符

运算符优先级

由高到低sizeof不是函数,而是运算符,如在malloc中常传入sizeof的运算结果,他是在运行之前就已经计算好了传入malloc函数中的

1.12 C++ 循环

循环类型

循环控制语句

1.13 C++ 判断

嵌套语句

switch中括号里面的结果必须是数值型的,单个的char也相当于数值,要是整个字符串(字符数组或者string),铁定用不成。如果需要在switch-case里面定义局部变量,case的语句需要加大括号。

? : 运算符

A ? B : c;

A真则B,A假为C。

1.14 C++函数

在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此第二条也是有效的声明:

int max(int num1, int num2);int max(int, int);

在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。应该在调用函数的文件顶部声明函数。

函数参数:

函数使用参数,必须声明接受参数值的变量。这些变量称为函数的形式参数

形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁

当调用函数时,有三种向函数传递参数的方式:

参数默认值

在函数定义中使用赋值运算符来为参数赋默认值。调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。

Lambda 函数与表达式

C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。

Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。

形式:

[capture](parameters)->return-type{body}# eg:[](int x, int y){ return x < y ; }# 无返回值:[capture](parameters){body}# eg:[]{ ++global_x; } # 返回值类型可以明确指定:[](int x, int y) -> int { int z = x + y; return z + x; }

在Lambda表达式内可以访问当前作用域的变量,这是Lambda表达式的闭包(Closure)行为。 与JavaScript闭包不同,C++变量传递有传值和传引用的区别。可以通过前面的[]来指定:

[]// 沒有定义任何变量。使用未定义变量会引发错误。[x, &y] // x以传值方式传入(默认),y以引用方式传入。[&]// 任何被使用到的外部变量都隐式地以引用方式加以引用。[=]// 任何被使用到的外部变量都隐式地以传值方式加以引用。[&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用。[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。

对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针。但是,对于[]的形式,如果要使用 this 指针,必须显式传入:

[this]() { this->someFunc(); }();

指针和引用的区别?

指针是*,通过它能找到以它为地址的内存单元。引用是&,就是某个变量的别名,对引用操作与对变量直接操作完全一样。区别: 引用必须要初始化。指针是个实体,而引用是别名。引用只能在定义时被初始化一次,之后不可变,指针可以改变所指的对象。可以有const指针,没有const引用。指针自加,是指向下一次地址,而引用自加:是本身值的增加。引用只能被初始化一次,不能再换成别的名字了。

指针调用与引用调用的区别在于:

指针变量存储的是一个指针,也就是一个存储地址,当使用指针作为形参的时候,可以改变指针的指向,访问该地址的数据时需要加上符号 * ;而引用调用他是直接将一个地址传递到函数内,相当于在该函数内给变量起了一个别名,不可改变指向,但可以改变该地址内所存储的值;

1.15 C++ 数字

int rand(void) 与 void srand(unsigned int seed) 头文件:#include<stdlib.h>用户未设定随机数种子时,系统默认的随机数种子为1。rand()产生的是伪随机数字,每次执行时是相同的;若要不同,用函数srand()初始化它。rand()和srand()要一起使用,其中srand()用来初始化随机数种子,rand()用来产生随机数。参数seed必须是个整数,通常可以利用time(0)的返回值或NULL来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。(失去随机性)可以把 seed 设为time(0)保证随机性。要产生 0–n 内的随机数:rand() % n;a–b 内的随机数a + rand() % (b - a + 1);左闭右开

1.16 C++ 数组

存储一个固定大小相同类型元素的顺序集合

所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素

声明数组

arraySize必须是一个大于零的整数常量,type可以是任意有效的 C++ 数据类型

type arrayName [ arraySize ];

初始化数组

如果不指定数组大小,则为初始化时元素的个数。

double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};

多维数组

type name[size1][size2]...[sizeN];

eg:初始化二维数组

int a[3][4] = { {0, 1, 2, 3} , /* 初始化索引号为 0 的行 */{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */{8, 9, 10, 11} /* 初始化索引号为 2 的行 */};// 等同于:int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

指向数组的指针

数组名是一个指向数组中第一个元素的常量指针

balance是一个指向 &balance[0] 的指针,即数组 balance 的第一个元素的地址。

double balance[50];// 把 p 赋值为 balance 的第一个元素的地址double *p;double balance[10];p = balance;

*(balance + 4)等同于*(p+4)即访问balance[4]的数据

从函数返回数组

C++ 不允许返回一个完整的数组作为函数的参数;可以通过指定不带索引的数组名来返回一个指向数组的指针。

想要从函数返回一个一维数组,您必须声明一个返回指针的函数,如下:

int * myFunction(){...}

C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为static变量

eg:生成 10 个随机数,并使用数组来返回它们

#include <iostream>#include <cstdlib>#include <ctime>using namespace std;// 要生成和返回随机数的函数int * getRandom( ){static int r[10];// 设置种子srand( (unsigned)time( NULL ) );for (int i = 0; i < 10; ++i){r[i] = rand();cout << r[i] << endl;}return r;}// 要调用上面定义函数的主函数int main (){// 一个指向整数的指针int *p;p = getRandom();for ( int i = 0; i < 10; i++ ){cout << "*(p + " << i << ") : ";cout << *(p + i) << endl;}return 0;}

1.17 C++ 字符串

C++ 提供了以下两种类型的字符串表示形式: C 风格字符串C++ 引入的 string 类类型

C 风格字符串

字符串实际上是使用null字符 ‘\0’ 终止的一维字符数组。

字符数组的大小比实际的字符数多一个。

C++ 编译器会在初始化数组时,自动把 ‘\0’ 放在字符串的末尾。

初始化:

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};// 或者:char greeting[] = "Hello";

可用函数:

示例:

#include <iostream>#include <cstring>using namespace std;int main (){char str1[11] = "Hello";char str2[11] = "World";char str3[11];int len ;// 复制 str1 到 str3strcpy( str3, str1);cout << "strcpy( str3, str1) : " << str3 << endl;// 连接 str1 和 str2strcat( str1, str2);cout << "strcat( str1, str2): " << str1 << endl;// 连接后,str1 的总长度len = strlen(str1);cout << "strlen(str1) : " << len << endl;system("pause");return 0;}// strcpy( str3, str1) : Hello// strcat( str1, str2): HelloWorld// strlen(str1) : 10

C++ 中的 String 类

C++ 标准库提供了string类类型,支持上述所有的操作,另外还增加了其他更多的功能。

示例:

#include <iostream>#include <string>using namespace std;int main (){string str1 = "Hello";string str2 = "World";string str3;int len ;// 复制 str1 到 str3str3 = str1;cout << "str3 : " << str3 << endl;// 连接 str1 和 str2str3 = str1 + str2;cout << "str1 + str2 : " << str3 << endl;// 连接后,str3 的总长度len = str3.size();cout << "str3.size() : " << len << endl;system("pause");return 0;}// str3 : Hello// str1 + str2 : HelloWorld// str3.size() : 10

1.18 C++ 指针

每个变量都有一个内存地址,用 “&” 访问地址。

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。声明:type *name;

所有指针的值的实际数据类型(整型、浮点型、字符型等)都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同

示例:

#include <iostream>using namespace std;int main (){int var = 20; // 实际变量的声明int *ip; // 指针变量的声明ip = &var; // 在指针变量中存储 var 的地址cout << "Value of var variable: ";cout << var << endl;// 输出在指针变量中存储的地址cout << "Address stored in ip variable: ";cout << ip << endl;// 访问指针中地址的值cout << "Value of *ip variable: ";cout << *ip << endl;return 0;}// Value of var variable: 20// Address stored in ip variable: 0xbfc601ac// Value of *ip variable: 20

C++ 指针详解:

空指针

变量声明时,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为指针。

NULL 指针是一个定义在标准库中的值为零的常量:

#include <iostream>using namespace std;int main (){int *ptr = NULL;cout << "ptr 的值是 " << ptr ;return 0;}// ptr 的值是 0

内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。

因此,如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。

空指针尽可能的使用nullptr

指针的算数运算

指针是一个用数值表示的地址。因此,可以对指针执行算术运算。

可以对指针进行四种算术运算:++(指向下一个变量的地址)、–(指向上一个变量的地址)、+、-。

经常用指针代替数组,因为变量指针可以递增,而数组不能递增,因为数组是一个常量指针。示例:

#include <iostream>using namespace std;const int MAX = 3;int main (){int var[MAX] = {10, 100, 200};int *ptr;// 指针指向数组第一个元素地址ptr = var;// 指针指向数组最后一个地址// ptr = &var[MAX-1]for (int i = 0; i < MAX; i++){cout << "Address of var[" << i << "] = ";cout << ptr << endl;cout << "Value of var[" << i << "] = ";cout << *ptr << endl;// 移动到下一个位置ptr++;// 移动到上一个位置ptr--;}return 0;}

指针的比较:

指针可以用关系运算符进行比较,如 ==、< 和 >。如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。

指针数组

让数组存储指向 int 或 char 或其他数据类型的指针

指向整数的指针数组的声明:int *ptr[MAX];

这里,把ptr声明为一个数组,由 MAX 个整数指针组成。因此,ptr 中的每个元素,都是一个指向 int 值的指针。

示例:把三个整数存储在一个指针数组中

#include <iostream>using namespace std;const int MAX = 3;int main (){int var[MAX] = {10, 100, 200};int *ptr[MAX];for (int i = 0; i < MAX; i++){ptr[i] = &var[i]; // 赋值为整数的地址}for (int i = 0; i < MAX; i++){cout << "Value of var[" << i << "] = ";cout << *ptr[i] << endl;}return 0;}// Value of var[0] = 10// Value of var[1] = 100// Value of var[2] = 200

指针数组 与 数组指针

int *p[n]为指针数组:即存放指针的数组,数组中有n个元素,每个元素为一个int型的指针;int (*p)[n]为数组指针:即指向数组的指针,p为一个指针,指向一个包含n个int元素的数组。数组和指针,在后面的为主语,前面的是定语,用来修饰主语。

指向指针的指针(多级间接寻址)

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。

通常,一个指针包含一个变量的地址。当定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

指向指针的指针变量声明:

int **var;

示例:

#include <iostream>using namespace std;int main (){int var;int *ptr;int **pptr;var = 3000;// 获取 var 的地址ptr = &var;// 使用运算符 & 获取 ptr 的地址pptr = &ptr;// 使用 pptr 获取值cout << "var 值为 :" << var << endl;cout << "*ptr 值为:" << *ptr << endl;cout << "**pptr 值为:" << **pptr << endl;return 0;}// var 值为 :3000// *ptr 值为:3000// **pptr 值为:3000

传递指针给函数

方法:声明函数参数为指针类型

示例:传递一个无符号的 long 型指针给函数

#include <iostream>#include <ctime>using namespace std;void getSeconds(unsigned long *par);int main (){unsigned long sec;getSeconds( &sec );// 输出实际值cout << "Number of seconds :" << sec << endl;return 0;}void getSeconds(unsigned long *par){// 获取当前的秒数*par = time( NULL );return;}

传递指针给函数

只需要声明函数参数为指针类型,并将地址传递给函数

示例:传递一个无符号的 long 型指针给函数,并在函数内改变这个值

#include <iostream>#include <ctime>using namespace std;void getSeconds(unsigned long *par);int main (){unsigned long sec;getSeconds( &sec );// 输出实际值cout << "Number of seconds :" << sec << endl;return 0;}void getSeconds(unsigned long *par){// 获取当前的秒数*par = time( NULL );return;}

同样,可以将数组传递给函数(能接受指针作为参数的函数,也能接受数组作为参数):

#include <iostream>using namespace std;// 函数声明double getAverage(int *arr, int size);int main (){// 带有 5 个元素的整型数组int balance[5] = {1000, 2, 3, 17, 50};double avg;// 传递一个指向数组的指针作为参数avg = getAverage( balance, 5 ) ;// 输出返回值cout << "Average value is: " << avg << endl; return 0;}double getAverage(int *arr, int size){int i, sum = 0; double avg;for (i = 0; i < size; ++i){sum += arr[i];}avg = double(sum) / size;return avg;}// Average value is: 214.4

从函数返回指针

首先声明一个返回指针的函数:(C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为static变量。)

int * myFunction(){...}

示例:

#include <iostream>#include <ctime>#include <cstdlib>using namespace std;// 要生成和返回随机数的函数int * getRandom( ){static int r[10];// 设置种子srand( (unsigned)time( NULL ) );for (int i = 0; i < 10; ++i){r[i] = rand();cout << r[i] << endl;}return r;}// 要调用上面定义函数的主函数int main (){// 一个指向整数的指针int *p;p = getRandom();for ( int i = 0; i < 10; i++ ){cout << "*(p + " << i << ") : ";cout << *(p + i) << endl;}return 0;}

1.19 C++ 引用

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

引用 vs 指针

区别:

不存在空引用。引用必须连接到一块合法的内存。一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。引用必须在创建时被初始化。指针可以在任何时间被初始化。引用不占内存,但指针是一个变量,是有自己的独立内存空间的

创建引用

变量名称是变量附属在内存位置中的标签,引用相当于是变量附属在内存位置中的第二个标签。可以通过原始变量名称或引用来访问变量的内容。

示例:

#include <iostream>using namespace std;int main (){// 声明简单的变量int i;double d;// 声明引用变量int& r = i;double& s = d;i = 5;cout << "Value of i : " << i << endl;cout << "Value of i reference : " << r << endl;d = 11.7;cout << "Value of d : " << d << endl;cout << "Value of d reference : " << s << endl;return 0;}// Value of i : 5// Value of i reference : 5// Value of d : 11.7// Value of d reference : 11.7

引用通常用于函数参数列表和函数返回值。

引用作为参数

#include <iostream>using namespace std;// 函数声明void swap(int& x, int& y);int main (){// 局部变量声明int a = 100;int b = 200;cout << "交换前,a 的值:" << a << endl;cout << "交换前,b 的值:" << b << endl;/* 调用函数来交换值 */swap(a, b);cout << "交换后,a 的值:" << a << endl;cout << "交换后,b 的值:" << b << endl;return 0;}// 函数定义void swap(int& x, int& y){int temp;temp = x; /* 保存地址 x 的值 */x = y; /* 把 y 赋值给 x */y = temp; /* 把 x 赋值给 y */return;}// 交换前,a 的值: 100// 交换前,b 的值: 200// 交换后,a 的值: 200// 交换后,b 的值: 100

引用作为返回值

通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。函数返回一个引用的方式与返回一个指针类似。

当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。

示例:

#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 在函数作用域外依然是有效的}

1.20 C++ 日期 & 时间

C++ 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用<ctime>头文件。

有四个与时间相关的类型:clock_t、time_t、size_ttm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。

结构类型tm把日期和时间以 C 结构的形式保存,tm 结构的定义如下:

struct tm {int tm_sec; // 秒,正常范围从 0 到 59,但允许至 61int tm_min; // 分,范围从 0 到 59int tm_hour; // 小时,范围从 0 到 23int tm_mday; // 一月中的第几天,范围从 1 到 31int tm_mon; // 月,范围从 0 到 11int tm_year; // 自 1900 年起的年数int tm_wday; // 一周中的第几天,范围从 0 到 6,从星期日算起int tm_yday; // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起int tm_isdst; // 夏令时}

函数:

参考:C/C++时间函数的用法 ()

1.21 C++ 基本输入输出

C++ 的 I/O 发生在流中,流是字节序列。 如果字节流是从设备(如键盘、磁盘驱动器、网络连接等)流向内存,这叫做输入操作。如果字节流是从内存流向设备(如显示屏、打印机、磁盘驱动器、网络连接等),这叫做输出操作

I/O 库头文件

标准输出流(cout)

预定义的对象coutiostream类的一个实例。cout 对象"连接"到标准输出设备,通常是显示屏。cout是与流插入运算符 << 结合使用的。cout << "Value of str is : " << 变量名 << endl;

标准输入流(cin)

预定义的对象ciniostream类的一个实例。cin 对象附属到标准输入设备,通常是键盘。cin是与流提取运算符 >> 结合使用的,如下所示:cin >> name流提取运算符 >> 在一个语句中可以多次使用,如果要求输入多个数据,可以使用如下语句:cin >> name >> age;

标准错误流(cerr)

预定义的对象cerriostream类的一个实例。cerr 对象附属到标准错误设备,通常也是显示屏,但是cerr对象是非缓冲的,且每个流插入到 cerr 都会立即输出。

cerr也是与流插入运算符 << 结合使用的,示例:

#include <iostream>using namespace std;int main( ){char str[] = "Unable to read....";cerr << "Error message : " << str << endl;}// Error message : Unable to read....

标准日志流(clog)

预定义的对象clogiostream类的一个实例。clog 对象附属到标准错误设备,通常也是显示屏,但是clog对象是缓冲的。这意味着每个流插入到 clog 都会先存储在缓冲区,直到缓冲填满或者缓冲区刷新时才会输出。

clog也是与流插入运算符 << 结合使用的,如下所示:

#include <iostream>using namespace std;int main( ){char str[] = "Unable to read....";clog << "Error message : " << str << endl;}// Error message : Unable to read....

1.22 C++ 结构体

结构体允许存储不同类型的数据项

定义:

struct type_name {member_type1 member_name1;member_type2 member_name2;member_type3 member_name3;..} object_names;

访问结构成员

使用成员访问运算符(.)

结构体可以作为函数参数

指向结构体的指针:

struct Books *struct_pointer;

使用指向该结构的指针访问结构的成员,使用->运算符

typedef 关键字

为创建的结构体起“别名”:直接使用Books来定义Books类型的变量,不需要使用 struct 关键字。

typedef struct Books{char title[50];char author[50];char subject[100];int book_id;}Books;// 使用:Books Book1, Book2;

也可以定义非结构体类型: x, y 和 z 都是指向长整型 long int 的指针。

typedef long int *pint32;pint32 x, y, z;

typedef 与 #define 的区别:

typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

参考:

/tutorial/10003/726e8520c91b40d8b26e2d9f8880b9e1

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。