最详细的讲解C++中指针的使用方法(通俗易懂)

一、指针的定义与使用

        指针是高级编程语言中非常重要的概念,在高级语言的编程中发挥着非常重要的作用,它能使得不同区域的代码可以轻易的共享内存数据。指针使得一些复杂的链接性的数据结构的构建成为可能,有些操作必须使用指针,比如申请堆内存,还有C++或者C语言中函数的调用中值传递都是按值传递的,如果在函数中修改被传递的对象,就必须通过这个对象指针来完成。指针就是内存地址,指针变量就是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因为数据类型不同,因此所占的存储空间长度也不同。使用指针不仅可以对数据本身,也可以对存储数据变量的地址进行操作。很多萌新在刚开始学习编程的时候会被指针搞蒙,那现在就让我给大家详细讲解指针的使用。

1、指针的引入(函数返回中return语句的局限性)

函数的缺陷:

一个函数只能返回一个值,就算我们在函数里面写多了return语句,但是只要执行任何一条return语句,整个函数调用就结束了。

数组可以帮助我们返回多个值,但是数组是相同数据类型的结合,对于不同数据类型则不能使用数组

使用指针可以有效解决这个问题,使用指针我们想反回几个值就能返回几个值,想返回什么类型就可以返回什么类型的值。在程序设计过程中,存入数据还是取出数据都需要与内存单元打交道,计算机通过地址编码来表示内存单元。指针类型就是为了处理计算机地址数据的,计算机将内存划分为若干个存储空间大小的单元,每个单元大小就是一个字节,即计算机将内存换分为一个一个的字节,然后为每一个字节分配唯一的编码,这个编码即为这个字节的地址。指针就是用来表示这些地址的,即指针型数据不是什么字符型数据,而存的是我们内存中的地址编码。指针可以提高程序的效率,更重要的是能使一个函数访问另一个函数的局部变量,指针是两个函数进行数据交换必不可少的工具。

地址及指针的概念:

程序中的数据(变量,数组等)对象总是存放在内存中,在生命期内这些对象占据一定的内存空间,有确定的存储位置,实际上,每个内存单元都有一个地址,即以字节为单位连续编码。编译器将程序中的对象名转换成机器指令识别的地址,通过地址来存储对象值。

int i;   double   f;

计算机为int 类型数据分配4个字节,为double 类型分配8个字节。按对象名称存取对象的方式成为对象直接访问,如:i=100;   f=3.14;   通过对象地址存取对象的方式成为指针间接访问

如图,这里有一个名为4000的存储空间它放的不是数值,而是  i  这个变量的地址,i  占有四个字节每个字节都有一个地址,这个变量的地址其实就是第一个字节的地址,在这里  i  的地址指就是他第一个字节的地址,假设第一个地址是4000,这里有一个p,先不管他是个啥东西,他占了一段存储空间,他里面放的就是  i  的地址,现在我们要访问  i  但是我们不直接访问,不出现  i  的名字,而是通过找到 p 得到了p里面放的 i 的地址以后就能间接的去访问 i ,就是说我们不是直接访问这个地址的,而是通过 P 这个量去访问 i  的值,这样的访问方式就叫做指针间接访问。即通过对象的地址来存储对象的方式称为指针间接访问。

现在我们来举个例子详细了解一下指针到底是一个什么东东

        一个快递员送快递,如果送的是一个老顾客,那么快递员可以直接跑到顾客的办公地点,将快递交给她就行了,这就是直接访问。但是如果现在快递员拿到了一个不认识的人的快递他是一个新顾客,那么快递员跑到他的办公地点,办公地点有很多人,他也分不清谁是谁,于是快递员找到了这里的一个保安问“张三是谁”保安就会给他指出张三就是这个人。然后快递员才能把快递送到顾客手上。此时这个中间来指出张三的人(保安)就是起了指针的作用,快递员无法直接找到张三,因此他只有通过保安才能给他指出张三是谁,这就叫做间接访问。

2、指针的定义形式方法及其含义

c++将专门用来存放对象地址的变量叫做指针变量,下面是指针变量定义形式:

指针类型* 指针变量名;
例如:
int* p, i;	//定义指针变量p,i为整形变量
p = &i;		//指针变量p指向i
把 i 的地址放到p

i  里放的是100这个数他的地址是4000,p里面放的就是i 的地址,然后就将p 指向i,他俩的关系即为p指向i,

假定指针变量p 的值是4000,三种写法:
char* p;
int* p;
double* p;
指针的类型其实就是它所指向的对象的类型

指针的类型:

         指针的类型表明的就是他所指向的对象的类型,把p定义为char类型,即用char类型的指针P来间接访问它指向的对象时我们间接引用的是一个字节的空间,假设p放的是4000,则系统会默认p指向的是4000这一个字节里面的内容,若将p定义成整形那么意味着我们用间接引用的方式来用指针指向对象的时候,系统就会认为你 的指针占4个字节这个对象就是4000,4001, 4002, 4003 这四个字节共同组成这个对象,若定义为double类型,那么系统就会认为他指向的对象时8个字节的即4000~~4007这八个字节都认为是P所指向的对象。这就是指针类型的含义,指针的类型应该和他指向的对象的类型一致,即整形指针应该指向整形变量,实型指针指向实型的变量。

3、通过指针间接访问

通过间接引用运算  *   可以访问指针所指向的对象或者内存单元,即在指针前面加上一个 * 就表明指针所引用的东西

int a, * p = &a;
a = 100;//直接访问a(对象直接访问)
*p = 100;//*p就是a,间接访问a(指针间接访问)
*p = *p + 1;//等价于a=a+1
int a, b, * p1 = &a, * p2;

&*p1 的含义:
&和*都是自右向左运算符,因此先看p1是指针,*p1即为p1指向的对象,
因此*p1等价于a,因此a 的前面加一个&,表示的就是 a 的地址
因此:&*p1 ,p1 ,&a 三者等价
*&a 的含义:a的地址前加*表示的就是a本身,指针就是用来放地址的,地址前面加*表示的就是这个对象
因此: *&a ,a ,*p 三者等价
int main()
{
	int i = 100, j = 200;
	int* p1, * p2;
	p1 = &i, p2 = &j;//p1指向i,p2指向j
	*p1 = *p1 + 1;//等价于i=i+1
	p1 = p2;//将p2的值赋给p1,则p1指向j
	*p1 = *p1 + 1;//等价于j=j+1
	return 0;
}

4、指针的初始化,可以在定义指针时对它进行初始化

指针类型* 指针变量名 = 地址初值,......

int a;
int* p = &a;//p的初值为变量a 的地址
int b, * p1 = &b;//p1初始化是变量b已有地址值

由于指针数据的特殊性,他的初始化和赋值运算是有约束条件的,只能使用以下四种值:
(1)0值常量表达式:
int a, z = 0;
int p1 = null;  //指针允许0值常量表达式
p1 = 0;//指针允许0只常量表达式

下面三中形式是错误的:
int* p1 = a;//错误  地址初值不能是变量
int p1 = z;//错误  整形变量不能作为指针,即使值为0
p1 = 4000;//错误,指针允许0值常量表达式

(2)相同指向类型的对象的地址。
int a, * p1;
double f, * p3;
p1 = &a;
p3 = &f;

p1 = &f;//错误p1和f指向类型不同
(3)相同指向类型的另一个有效指针
int x, * px = &x;
int* py = px;//相同指向类型的另一个指针
(4)对象存储空间后面下一个有效地址,如数组下一个元素的地址
int a[10], * px = &a[2];
int* py = &a[++i];

5、指针运算

指针运算都是作用在连续存储空间上才有意义。

(1)指针加减整数运算
int x[10], n = 3, * p = &x[5];
p + 1		//指向内存空间中x[5]后面的第1个int 型存储单元
p + n		//--------------------------n(3)个
p - 1		//-------------------前面-----1个
p - n		//

(2)指针变量自增自减运算
int x[10], * p = &x[5];
p++		//p指向x[5]后面的第1个int型内存单元
++p		//-----------------1--------------
p--		//p指向x[5]前面的第1个int型内存单元
--p		//--------------------------------

(3)两个指针相减运算
设p1, p2是相同类型的两个指针,则p2 - p1的结果是两支针之间对象
的个数,如果p2指针地址大于p1则结果为正,否则为负
int x[5], * p1 = &x[0], * p2 = &x[4];
int n;
n = p2 - p1;//n 的值为4  即为他们之间间隔的元素的个数
运算方法:(p2储存的地址编码-p1储存的地址编码)/4  若是double类型则除以8  char类型除以1

(1)指针加减整数运算
int x[10], n = 3, * p = &x[5];
p + 1		//指向内存空间中x[5]后面的第1个int 型存储单元
p + n		//--------------------------n(3)个
p - 1		//-------------------前面-----1个
p - n		//

(4)指针的运算关系
设p1、p2是同一个指向类型的两个指针,则p1和p2可以进行关系运算,
用于比较这两个地址的位置关系即哪一个是靠前或者靠后的元素
int x[4], * p1 = &x[0], * p2 = &x[4];
p2 > p1;   //表达式为真

6、指针的const限定

(1)一个指针变量可以指向只读型对象,称为指向const对象的指针定义形式是:

const 指向类型  *指针变量,...

即在指针变量前加const限定符,其含义是不允许通过指针来改变所指向的const对象的值,不能通过间接引用来改变它所指向的对象的值

const int a = 10, b = 20;
const int* p;
p = &a;//正确 p不是只读的,把a的地址赋给p,给p赋值是允许的
p = &b;//正确,p不是只读的
*p = 42;//把42赋给p所指向的对象。错误,*p是只读的

(2)把一个const对象的地址赋给一个非const对象的指针是错误的,例如:

const double pi = 3.14;
double* ptr = π//错误,ptr是非const所指向的变量
const double* cptr = π//正确,cptr是const指针变量

(3)允许把非const对象的地址赋给指向const对象的指针,不能使用指向const对象的指针修改指向对象,然而如果该指针指向的是一个非const对象,可以用其他方法修改其所指向的对象

const double pi = 3.14;
const double* cptrf = π//正确
double f = 3.14;//f是double类型(非const类型)
cptr = &f;//正确,允许将f的地址赋给cptrf
f = 1.68;//正确,允许修改f的值
*cptrf = 10.3;//错误不能通过引用cptr修改f的值

(4)实际编程过程中,指向const的指针常用作函数的形参,以此确保传递给函数的参数对象在函数中不能被修改

void fun(const int* p)
{
	...
}

int main()
{
	int a;
	fun(&a);
}
指针作为函数的形参,在主函数中,我们定义整形变量a然后将a的地址传递给了子函数,对于子函数来说,
他的形参就是用const修饰过 的整型变量p指向主函数里a这个变量
这样的一系列操作就使得我们不能在子函数中通过p间接引用a 来改变a 的值,因为a 是用const修饰过的作就使得我们不能在子函数中通过p间接引用a 来改变a 的值,因为a 是用const修饰过的

7、const指针

一个指针变量可以是只读的,成为const指针它的定义形式:

指针类型* const 指针变量, ...;
注意观察将const放在变量名的前面,与上面的形式不同,

int a = 10, b = 20;
int* const pc = &a;//pc是const指针
pc = &b;//错误pc 是只读的
pc = pc;//错误pc是只读的
pc++;//错误pc是只读的
*pc = 100;//正确,a被修改

pc是指向int型对象的const指针

不能使pc再被赋值指向其他对象,任何企图给const指针赋值的操作都会导致编译错误

但是可以通过pc间接引用修改该对象的值

二、一维数组与指针

1、数组的首地址

数组有若干个元素组成,每个元素都有相应的地址,通过取地址运算符&可以得到每个元素的地址,数组的地址就是这一整块存储空间中,第一个元素的地址即a[0]

int a[10];
int* p = &a[0];//定义指向一维数组元素的指针,用a数组的地址来初始化p,称p指向a
p = &a[5];//指向a[5] 重新给p赋值,指针数组元素的地址跟取变量的地址是一样的效果,
c++中规定数组名既代表数组本身,又代表整个数组的地址,还是数组首元素的地址值即:与a第0个元素的地址& a[0]相同
例如:
下面两个语句是等价的:
p = a;
p = &a[0];

数组名是一个指针常量,因而他不能出现在左值和某些算数运算中
例如:
int a[10], b[10], c[10];
a = b;//错误,a是常量,不能出现在左值的位置
c = a + b;//错误,a,b是地址值,不允许加法运算
a++;//错误,a 是常量不能使用++运算

2、指向一维数组的指针变量

定义指向一维数组元素的指针变量时,指向类型应该与数组元素类型一致

int a[10], * p1;
double f[10], * p2;
p1 = a;//正确
p2 = f;//正确
p1 = f;//错误,指向类型不同不能赋值

3、通过指针访问一维数组

由于数组的元素地址是规律性增加的,根据指针 运算规律,可以利用指针及其运算来访问数组元素

int* p, a[10] = { 1,2,3,4,5,6,7,8,9,0 };
p = a;//指向数组a,其实就是让p指向了a[0]
p++;//指向了下一个数组元素即a[1]

根据上图,我们设:

a是一个一维数组,p是指针变量,且p=a;下面我们来访问一个数组元素 a[i];

(1)数组下标法:a[i];

(2)指针下标法:p[i];  p里面已经放了数组的地址了,因此数组名和p 是等价的所以  p[i]与a[i]含义相同

(3)地址引用法:*(a+i);  a表示的是下标为0 的元素的地址  (a+i) 即为a这个数组往后数第 i  个元素的地址 即第 i 个元素的地址  那么*(a+i)相当于地址再加一个星号表示的就是这个地址对应的存储单元,或者说对应的对像即为 a[i]这个元素

(4)指针引用法:*(p+i);将a替换成p跟(3)含义相同

下面我们用多种方法来遍历一维数组元素:

(1)下标法:优点是程序写法直观,能直接知道访问的是第几个元素

#include<iostream>
using namespace std;
int main()
{
	int a[4];
	for (int i = 0; i < 4; i++)
		cin >> a[i];
	for (int i = 0; i < 4; i++)
		cout << a[i] << " ";
	return 0;
}

(2)通过地址间接访问数组元素

#include<iostream>
using namespace std;
int main()
{
	int a[5],i;
	for (i = 0; i < 5; i++)
		cin >> *(a + i);
	for (i = 0; i < 5; i++)
		cout << *(a + i) << " ";
}

(3)通过指向数组的指针变量间接访问数组,用指针作为循环控制变量  优点是指针直接指向元素,不必每次都重新计算地址,能提高运行效率(我们用P某一个元素的时候p本身已经放了这个元素的地址,因此计算机就不用再去计算这个元素的地址,因为取一个元素的时候要先知道他的地址),将自增自减运算用于指针变量十分有效,可以使指针变量自动向前或者向后指向数组的下一个或前一个元素

#include<iostream>
using namespace std;
int main()
{
	int a[5], * p;
	for (p = a; p < a + 5; p++)
		cin >> *p;
	for (p = a; p < a + 5; p++)
		cout << *p << " ";
}

指针p初值为a,即一开始指向元素a[0],指针可以进行比较运算 p

cin>>*p;即为间接的引用了p所指向的数组元素。

三、用指针来操纵字符串

可以利用一个字符型的指针来处理字符串,其中过程与通过指针访问数组元素相同,使用指针可以简化字符串的处理。

c++允许定义一个字符指针,初始化是指向一个字符常量,一般形式为:

char* p = "C Language";
或者
char* p;
p="C Language"

初始化时,p存储了这个字符串字符地址,而不是字符串常量本身,相当于char类型的指针指向"C Language"这个字符串的首地址,即第一个元素C的地址称p指向字符串

下面我们通过字符串指针来访问字符串

char str[] = "C Language", * p = str;//p指向字符串的指针相当于p指向了str[0]
cout << p << endl;//输出:C Language  跟cout<<str<<endl;效果相同
cout << p + 2 << endl;//输出:Language 从字符L开始输出直到结束
cout << &str[7] << endl;//输出:age   从第7个元素开始输出
#include<iostream>
using namespace std;
int main()
{
	char str[] = "C language", * p = str;
	cout << p << endl;
	return 0;
}

运行结果:

#include<iostream>
using namespace std;
int main()
{
	char str[] = "C language";
	char* p = str;
	cout << p+2 << endl;
	return 0;
}

#include<iostream>
using namespace std;
int main()
{
	char str[] = "C Language";
	char* p = str;
	cout << p << endl;
	cout << p+2 << endl;
	cout << &str[7] << endl;
	return 0;
}

通过字符指针来遍历字符串

char str[] = "C Language", * p = str;
while (*p!='\0')cout << *p++;
判断p指向的元素是不是字符串结束的标志*p++ 的含义:先输出p指向的元素然后p++(后置增增,先做完其他事再自增)
假设从str[0]开始,p指向的是C满足(*p!='\0')因此执行循环,下一个循环p指向“空格”不是字符串结束的标志,继续
循环直到遇到字符串结束的标志后结束循环

举例:

#include<iostream>
using namespace std;
int main()
{
	char str[100], * p = str;
	cin >> str;
	while (*p)p++;
	cout << "strlen=" << p - str << endl;
	return 0;
}

while(*p)p++;的含义:进入循环判断逻辑值p是否为真,(非零为真,零为假)即判断p是否指向字符串结束标志(字符串结束标志符ASLL码为0)若p指向的字符不是空字符则括号内容为真执行循环p++(p指向下一个字符),否则结束循环

p-str为指针相减运算即看这两个指针中间相隔了多少个元素,这里的p已经是字符串结束标志,str表示的str[0]

注意:

指针可以指向数组,这使得数组访问多了一种方式,单指针不能代替数组存储大批量元素

char s[100] = "Computer";
s是数组名不能赋值,自增自减运算
char* p = "Computer";
p是一个指针,他存放的是这个字符串的首地址
p是一个指针变量,他能指向这个字符串也能指向其他东西可以进行赋值和自增自减

1、存储内容不同
2、运算方式不同
3、赋值操作不同
s一旦赋初值之后就不能再用其他字符来赋值,然而p却能重新指向其他字符

 

int a = 10, * p;
int& b = a;
p = &a;
string s = "C++";
string* ps = &s;
cout << p << endl;  //输出指针p的值,a变量的首地址
cout << b << endl;  //输出b的值是10
cout << *p << endl;  //输出指针p指向的变量,即a的值10
cout << ps << endl;;  //输出指针ps的值,s变量的地址
cout << *ps << endl; //输出指针ps指向的变量的值,即“C++”

二维数组字符串:

char s[6][7] = { "C++","Java","C","PHP","CSharp","Basic" };

内存形式

615134

  • 123
    点赞
  • 333
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
目 录 译者序 前言 第1章 对象的演化 1.1 基本概念 1.1.1 对象:特性+行为 1.1.2 继承:类型关系 1.1.3 多态性 1.1.4 操作概念:OOP程序像什么 1.2 为什么C++会成功 1.2.1 较好的C 1.2.2 采用渐进的学习方式 1.2.3 运行效率 1.2.4 系统更容易表达和理解 1.2.5 “库”使你事半功倍 1.2.6 错误处理 1.2.7 大程序设计 1.3 方法学介绍 1.3.1 复杂性 1.3.2 内部原则 1.3.3 外部原则 1.3.4 对象设计的五个阶段 1.3.5 方法承诺什么 1.3.6 方法应当提供什么 1.4 起草:最小的方法 1.4.1 前提 1.4.2 高概念 1.4.3 论述(Treatment) 1.4.4 结构化 1.4.5 开发 1.4.6 重写 1.4.7 逻辑 1.5 其他方法 1.5.1 Booch 1.5.2 责任驱动的设计(RDD) 1.5.3 对象建模技术(OMT) 1.6 为向OOP转变而采取的策略 1.6.1 逐步进入OOP 1.6.2 管理障碍 1.7 小结 第2章 数据抽象 2.1 声明与定义 2.2 一个袖珍C库 2.3 放在一起:项目创建工具 2.4 什么是非正常 2.5 基本对象 2.6 什么是对象 2.7 抽象数据类型 2.8 对象细节 2.9 头文件形式 2.10 嵌套结构 2.11 小结 2.12 练习 第3章 隐藏实现 3.1 设置限制 3.2 C++的存取控制 3.3 友元 3.3.1 嵌套友元 3.3.2 它是纯的吗 3.4 对象布局 3.5 类 48 3.5.1 用存取控制来修改stash 3.5.2 用存取控制来修改stack 3.6 句柄类(handle classes) 3.6.1 可见的实现部分 3.6.2 减少重复编译 3.7 小结 3.8 练习 第4章 初始化与清除 4.1 用构造函数确保初始化 4.2 用析构函数确保清除 4.3 清除定义块 4.3.1 for循环 4.3.2 空间分配 4.4 含有构造函数和析构函数的stash 4.5 含有构造函数和析构函数的stack 4.6 集合初始化 4.7 缺省构造函数 4.8 小结 4.9 练习 第5章 函数重载与缺省参数 5.1 范围分解 5.1.1 用返回值重载 5.1.2 安全类型连接 5.2 重载的例子 5.3 缺省参数 5.4 小结 5.5 练习 第6章 输入输出流介绍 6.1 为什么要用输入输出流 6.2 解决输入输出流问题 6.2.1 预先了解操作符重载 6.2.2 插入符与提取符 6.2.3 通常用法 6.2.4 面向行的输入 6.3 文件输入输出流 6.4 输入输出流缓冲 6.5 在输入输出流查找 6.6 strstreams 6.6.1 为用户分配的存储 6.6.2 自动存储分配 6.7 输出流格式化 6.7.1 内部格式化数据 6.7.2 例子 6.8 格式化操纵算子 6.9 建立操纵算子 6.10 输入输出流实例 6.10.1 代码生成 6.10.2 一个简单的数据记录 6.11 小结 6.12 练习 第7章 常量 7.1 值替代 7.1.1 头文件里的const 7.1.2 const的安全性 7.1.3 集合 7.1.4 与C语言的区别 7.2 指针 7.2.1 指向const的指针 7.2.2 const指针 7.2.3 赋值和类型检查 7.3 函数参数和返回值 7.3.1 传递const值 7.3.2 返回const值 7.3.3 传递和返回地址 7.4 类 7.4.1 类里的const和enum 7.4.2 编译期间类里的常量 7.4.3 const对象和成员函数 7.4.4 只读存储能力 7.5 可变的(volatile) 7.6 小结 7.7 练习 第8章 内联函数 8.1 预处理器的缺陷 8.2 内联函数 8.2.1 类内部的内联函数 8.2.2 存取函数 8.3 内联函数和编译器 8.3.1 局限性 8.3.2 赋值顺序 8.3.3 在构造函数和析构函数里隐藏行为 8.4 减少混乱 8.5 预处理器的特点 8.6 改进的错误检查 8.7 小结 8.8 练习 第9章 命名控制 9.1 来自C语言的静态成员 9.1.1 函数内部的静态变量 9.1.2 控制连接 9.1.3 其他的存储类型指定符 9.2 名字空间 9.2.1 产生一个名字空间 9.2.2 使用名字空间 9.3 C++的静态成员 9.3.1 定义静态数据成员的存储 9.3.2 嵌套类和局部类 9.3.3 静态成员函数 9.4 静态初始化的依赖因素 9.5 转换连接指定 9.6 小结 9.7 练习 第10章 引用和拷贝构造函数 10.1 C++指针 10.2 C++的引用 10.2.1 函数的引用 10.2.2 参数传递准则 10.3 拷贝构造函数 10.3.1 传值方式传递和返回 10.3.2 拷贝构造函数 10.3.3 缺省拷贝构造函数 10.3.4 拷贝构造函数方法的选择 10.4 指向成员的指针
### 回答1: 《Effective C++ 文第三版》是针对C++程序设计语言的一本重要的专业书籍,它将C++语言的各种语法特性、设计模式及编程技巧进行了深度分析和系统总结。 本书分为55条编程指南,从C++语言的核心概念(如RAII、异常安全等)到编程技巧的细节(如拷贝控制、继承、模板等)都进行了详细介绍。每个指南都包含了对应的问题、建议和说明,通过实际例子和对比分析,让读者能够更好地理解和掌握相关知识。 相比其他的C++规范书籍,《Effective C++ 文第三版》更加实用和直观,它的重点在于介绍如何写出正确、高效、健壮的C++代码。同时,书还对C++11和C++14的新特性进行了简单介绍,为读者扩展了视野,帮助读者更好地应对日益复杂的编程需求。 总的来说,《Effective C++ 文第三版》是一本适合C++程序员的入门和进阶教材,通过系统性的介绍和实例讲解,能够帮助读者逐步掌握C++语言的精髓和技巧,写出更加高效、健壮和易维护的程序。 ### 回答2: 《Effective C++ 文第三版》是一本介绍C++编程技巧的经典书籍。该书作者Scott Meyers是一位C++专家,他精心编写了该书的内容,用通俗易懂的语言阐述了C++编程的许多细节问题。通过学习这本书,读者可以更好地理解C++的语言特性,掌握C++编程的技巧和方法,以提高程序的质量和效率。 该书涵盖了37个条款,主要分为四个部分。第一部分介绍了C++语言的基础知识,包括构造函数和析构函数、赋值操作、拷贝构造函数等;第二部分介绍了C++的设计和实现,包括类设计、模板使用和异常处理等;第三部分介绍了C++的继承和多态,包括虚函数、抽象类、多重继承、虚继承等;第四部分介绍了C++的高级语言特性,包括模板元编程、异常安全、性能优化和智能指针等。 通过学习这本书,读者可以获得以下几个方面的收获。首先,掌握C++编程的基本技能和知识,能够写出高质量的、健壮的C++程序;其次,了解C++语言的设计和实现原理,能够更好地理解C++程序的内部机制;最后,学会了高效的C++编程技巧和方法,可以提高程序的性能和效率,避免常见的、容易犯的C++编程错误。 总之,《Effective C++ 文第三版》是一本非常优秀的C++编程书籍,对于想要成为一名优秀的C++程序员的读者来说,是一本不可多得的好书。 ### 回答3: Effective C++是一本非常经典的C++编程技巧指南,被誉为C++编程者必读的参考书之一。作者Scott Meyers深入浅出的将自己多年的实际经验和对C++各个方面的深入理解融合到了书,为读者提供了各种实用技巧和解决方案。本书被分成了50个小节,每个小节都介绍一个C++编程的技巧,如何避免陷阱以及如何让代码更加清晰可读。 Effective C++文第三版在前两版的基础上做了一些更新和补充,和当前主流的C++版本兼容,增加了对多线程编程方面的内容和对垃圾回收的讲解等等。此外,本书还提供了大量的实际例子和细节解释,让读者能够更好地理解和运用这些技巧。不仅适合初学者,对于已经上手C++编程的程序员也是一本非常有价值的参考书,可以帮助他们更好的掌握C++语言,并写出高效、可维护的代码。 总的来说,Effective C++C++编程界的经典书籍之一,具有极高的实用价值和指导意义。不同阶段的程序员都可以从获益,提高自己的编程能力。因此,对于想要成为一名优秀的C++程序员的人来说,这本书是绝不能缺少的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值