一、C++结构体相关知识
一段代码阐释所有初始化与赋值的情况:
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
//结构体初始化的几种方式
//定义一个node结构体
typedef struct node{
int id;
int num;
string name;
//1、无参数的构造函数数组初始化时调用
//node():id(),num(),name(){};
//有参构造
//node(int a,int b,string c):id(a),num(b),name(c){}
//2、对于方法3的构造函数初始化,什么都不写就是使用的结构体自带的默认构造函数。
//如果自己重写了带参数的构造函数,就不能用大括号进行初始化了,即不能再使用指定初始化与顺序初始化了(初始化结构体时如果不传入参数会出现错误)。
//在建立结构体数组时,如果只写了带参数的构造函数将会出现数组无法初始化的错误
//3、放在最后的构造函数可以不加分号结尾
//node(int id,int num,string name){
// this->id=id;
// this->num=num;
// this->name=name;
// }
} node_t;
typedef struct charnode{
int id;
int num;
char name[16];
} charnode_t;
struct Test {
int x = 0; // <== 含有默认初始化值的元素,无法使用初始化列表进行初始化
char v;
};
class Hero {
public:
Hero() {
cout << "Hero 构造函数调用了" << endl;
}
//如果用下面的free释放new出来的h2内存,将不会触发下面的析构函数
//Hero *h2 = new Hero;
//free(h2);
~Hero() {
cout << "Hero 析构函数调用了" << endl;
}
};
struct Date{
int day, month, year;
};
int main(){
//初始化的几种方法
//1、顺序初始化
node node1st={
1,2,"node1st"};
// node node1st;
cout<<node1st.name<<"---"<<"size:"<<sizeof(node1st)<<endl;
//2、指定初始化(点号+赋值符号或者使用冒号)
struct node node2st={
.id=2,num:5,name:"node2st"};
cout<<node2st.name<<endl;
//3、构造函数初始化
//构造函数初始化常见于 C++ 代码中,因为 C++ 中的 struct 可以看作 class,结构体也可以拥有构造函数
//struct 如果定义了构造函数的话,就不能用大括号进行初始化了,即不能再使用指定初始化与顺序初始化了
node_t node3st(5,6,"node3st");
cout<<node3st.name<<endl;
//4、使用calloc分配并置为0
node_t * node4st=(node_t *)calloc(1,sizeof(struct node));
std::cout << node4st->name<<"--point size:"<<sizeof(node4st)<<endl;
//5、使用new动态创建结构体变量时,必须是结构体指针类型
node_t * node5st=new node();
//虽说delete可以释放calloc的内存,但是我编译器还是报错了,还是得用free来释放
delete node5st;
// free(node5st);
//6、结构体变量使用结构体+()可以初始一个结构体变量的(也就创建了一个新的引用)
node node6st;
node6st=node();
cout<<node6st.name<<"--node6st--"<<"size:"<<sizeof(node6st)<<endl;
//7、以前是可以部分初始化的,但部分初始化只限于初始化开头的变量,如果某个结构成员未被初始化,则所有跟在它后面的成员都需要保留为未初始化
//不过我的编辑器部分初始化也报错了,感觉可能部分初始化风险较大吧
// Date birthday = {23,8};
//结构体赋值的几种方法
//变量的赋值和初始化是不一样的,初始化是在变量定义的时候完成的,是属于变量定义的一部分,赋值是在变量定义完成之后想改变变量值的时候所采取的操作
//无法使用node1st={1,2,"node1st"};这种方式赋值
//1、使用 memset 对结构体变量进行置空操作
//如下,使用memset进行赋值时,结构体里不能是string类型,但可以是char或char*
charnode_t node1ass;
// 按照编译器默认的方式进行初始化(如果node4st是全局静态存储区的变量,默认初始化为0,如果是栈上的局部变量,默认初始化为随机值)
memset(&node1ass,0,sizeof(charnode_t));
cout<<node1ass.name<<endl;
//2、依次给每一个结构体成员变量进行赋值
node_t node2ass;
node2ass.id=5;
node2ass.name="node2ass";
cout<<node2ass.name<<endl;
//3、使用已有的结构体变量给另一个结构体变量赋值(结构体变量之间是可以相互赋值的)
node_t node3ass;
node3ass=node1st;
cout<<node3ass.name<<endl;
//ps:初始化与赋值有着本质的区别,初始化是变量定义时的第一次赋值,赋值则是定义之后的值的变更操作
node3ass.name="node3ass";
cout<<node3ass.name<<"--"<<node1st.name<<endl;
//4、使用指针指向一个结构体变量
node_t *node4ass;
// node4ass=&node1st;
node4ass=node4st;
cout<<node4ass->name<<endl;
node4ass->name="node4ass";
// cout<<node4ass->name<<"--"<<node1st.name<<endl;
cout<<node4ass->name<<"--"<<node4st->name<<endl;
//1、delete主要用来释放new分配的内存,但delete 也可以用来释放由 malloc 和 calloc 分配的内存
// delete node4ass;
// delete node4st;
//2、free主要用来释放由 malloc 和 calloc 分配的内存,也可以释放new 分配的内存,但不推荐使用
free(node4ass);
// free(node4st);
// cout<<node4ass->name<<"--"<<node4st->name<<endl;
//char *c1 = (char *)malloc(1, 10);
//c1[0] = 'a';
//delete[] c1;
//经过 delete 释放过后,指针变成了野指针,此时再访问内存将是非法的,没有任何数据的,所以会显示乱码
//free(c1);
//不要使用 free 去释放由 new 分配的内存,因为它 不会去触发析构函数