一、指针运算符
C++ 提供了两种指针运算符,一种是取地址运算符 &,一种是间接寻址运算符 *
& 是一元运算符,返回操作数的内存地址。例如,如果 var 是一个整型变量,则 &var 是它的地址。该运算符与其他一元运算符具有相同的优先级,在运算时它是从右向左顺序进行的。 & 运算符读作"取地址运算符",这意味着,&var 读作"var 的地址"。
间接寻址运算符 *,它是 & 运算符的补充。* 是一元运算符,返回操作数所指定地址的变量的值。
箭头运算符与点运算符有关,对于一个指针ptr,表达式ptr->mem等价于(*ptr).mem;
string s1 = "a string",*p = &s1;
auto n = s1.size();//运行string对象s1的size()成员
n = (*p).size();//运行p所指对象的size成员
n = p->size(;)//等价于(*p).size
//点运算符针对对象和对象的成员,箭头运算符针对的是指针和成员;
#include <iostream>
using namespace std;
int main ()
{
int var;
int *ptr;
int val;
var = 3000;
// 获取 var 的地址
ptr = &var;//ptr存放取出来的地址
// 获取 ptr 的值
val = *ptr;//*寻找地址的内容,存放在val中
cout << "Value of var :" << var << endl;
cout << "Value of ptr :" << ptr << endl;
cout << "Value of val :" << val << endl;
return 0;
}
//编译结果
Value of var :3000
Value of ptr :0xbff64494
Value of val :3000
二、typedef struct和struct
(此处博客链接https://www.cnblogs.com/qyaizs/articles/2039101.html以及参考c语言中文网)
1.在C中定义一个结构体类型要用typedef:
typedef struct Student
{
int a;
}Stu;
于是在声明变量的时候就可:Stu stu1;(如果没有typedef就必须用struct Student stu1;来声明)
这里的Stu实际上就是struct Student的别名。Stu==struct Student
另外这里也可以不写Student(于是也不能struct Student stu1;了,必须是Stu stu1;)
c语言使用例子:
(char* 是声明一个字符类型的指针。比如:chat* y;就是声明一个指针y,这个指针指向的地址上只能存放字符类型的值。
指针即为地址,指针几个字节跟语言无关,而是跟系统的寻址能力有关。比如以前是16位系统,指针即为2个字节,现在一般是32位系统,所以是4个字节)
如果只需要 stu1、stu2 两个变量,后面不需要再使用结构体名定义其他变量,那么在定义时也可以不给出结构体名,如下所示:
struct{ //没有写 stu
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1, stu2;
//这样做书写简单,但是因为没有结构体名,后面就没法用该结构体定义新的变量
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1, stu2;
//声明一个变量用 struct stu stu1
#include <stdio.h>
int main(){
struct{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
} stu1;
//给结构体成员赋值
stu1.name = "Tom";
stu1.num = 12;
stu1.age = 18;
stu1.group = 'A';
stu1.score = 136.5;
//读取结构体成员的值
printf("%s的学号是%d,年龄是%d,在%c组,今年的成绩是%.1f!\n", stu1.name, stu1.num, stu1.age, stu1.group, stu1.score);
return 0;
}
//也可以在定义时整体赋值
struct{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
} stu1, stu2 = { "Tom", 12, 18, 'A', 136.5 };
但在c++里很简单,直接
struct Student
{
int a;
};
于是就定义了结构体类型Student,声明变量时直接Student stu2;
c++使用
#include <iostream>
#include <cstring>
using namespace std;
// 声明一个结构体类型 Books
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
Books Book1; // 定义结构体类型 Books 的变量 Book1
Books Book2; // 定义结构体类型 Books 的变量 Book2
// Book1 详述
strcpy( Book1.title, "C++ 教程");
strcpy( Book1.author, "Runoob");
strcpy( Book1.subject, "编程语言");
Book1.book_id = 12345;
// Book2 详述
strcpy( Book2.title, "CSS 教程");
strcpy( Book2.author, "Runoob");
strcpy( Book2.subject, "前端技术");
Book2.book_id = 12346;
// 输出 Book1 信息
cout << "第一本书标题 : " << Book1.title <<endl;
cout << "第一本书作者 : " << Book1.author <<endl;
cout << "第一本书类目 : " << Book1.subject <<endl;
cout << "第一本书 ID : " << Book1.book_id <<endl;
// 输出 Book2 信息
cout << "第二本书标题 : " << Book2.title <<endl;
cout << "第二本书作者 : " << Book2.author <<endl;
cout << "第二本书类目 : " << Book2.subject <<endl;
cout << "第二本书 ID : " << Book2.book_id <<endl;
return 0;
}
2.
在c++中如果用typedef的话,又会造成区别:
struct Student
{
int a;
}stu1;//stu1是一个变量
typedef struct Student2
{
int a;
}stu2;//stu2是一个结构体类型=struct Student
使用时可以直接访问stu1.a
但是stu2则必须先 stu2 s2;
然后 s2.a=10;
3.结构体是一种自定义的数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据,需要内存空间来存储
4.理论上讲结构体的各个成员在内存中是连续存储的,和数组非常类似,例如上面的结构体变量 stu1、stu2 的内存分布如下图所示,共占用 4+4+4+1+4 = 17 个字节
但是在编译器的具体实现中,各个成员之间可能会存在缝隙,对于 stu1、stu2,成员变量 group 和 score 之间就存在 3 个字节的空白填充(见下图)。这样算来,stu1、stu2 其实占用了 17 + 3 = 20 个字节。
三、指向结构体的指针
结构体变量的指针就是该变量那个所占据的内存段的起始地址。可以设一个指针变量,来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址
创建的对象 stu 在栈上分配内存,需要使用 &
获取它的地址,例如:Student stu;Student *pStu = &stu;
pStu 是一个指针,它指向 Student 类型的数据,也就是通过 Student 创建出来的对象
你也可以在堆上创建对象,这个时候就需要使用前面讲到的new
关键字:
Student *pStu = new Student;
在栈上创建出来的对象都有一个名字,比如 stu,使用指针指向它不是必须的。但是通过 new 创建出来的对象就不一样了,它在堆上分配内存,没有名字,只能得到一个指向它的指针,所以必须使用一个指针变量来接收这个指针,否则以后再也无法找到这个对象了,更没有办法使用它。也就是说,使用 new 在堆上创建出来的对象是匿名的,没法直接使用,必须要用一个指针指向它,再借助指针来访问它的成员变量或成员函数。
栈内存是程序自动管理的,不能使用 delete 删除在栈上创建的对象;堆内存由程序员管理,对象使用完毕后可以通过 delete 删除。在实际开发中,new 和 delete 往往成对出现,以保证及时删除不再使用的对象,防止无用内存堆积
有了对象指针后,可以通过箭头->
来访问对象的成员变量和成员函数,这和通过结构体指针(http://c.biancheng.net/view/246.html)来访问它的成员类似,请看下面的示例:
pStu -> name = "小明";
pStu -> age = 15;
pStu -> score = 92.5f;
pStu -> say();
//完整例子
#include <iostream>
using namespace std;
class Student{
public:
char *name;
int age;
float score;
void say(){
cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;
}
};
int main(){
Student *pStu = new Student;
pStu -> name = "小明";
pStu -> age = 15;
pStu -> score = 92.5f;
pStu -> say();
delete pStu; //删除对象
return 0;
}