c++ 初学 易错点 知识点

语法初学易忘点

1、cout << << endl;
2、求数组长度 可用

length=sizeof(num)/sizeof(num[0];

求数组首地址 可以直接输出 数组名

  cout<< num<<endl;//二维数组同理

3、求二维数组内存占用,行数,列数

  int num[4][5] = {  };
  
  cout << "二维数组占用总内存" << sizeof(num) << endl;
  cout <<"行占用内存大小"<<sizeof(num[0]);
  cout << "二维数组行数" << sizeof(num) / sizeof(num[0]) << endl;
  cout << "二维数组列数" << sizeof(num[0]) / sizeof(num[0][0])<<endl;
  ```
4、地址强制转换成十进制可以用 (int)强制转换

5、 查看数组中的某个地址 用&num[1][3],然后打印即可

6、包含头文件<string>后 可以用string 关键字定义字符串或字符数组。

7、分文件步骤 
(1)在新建的 .h头文件中写声明;
(2)在新建的 .app源文件中写定义;
(3)在头文件中包含新建源文件所需的头文件
(4)自己分的文件需用双引号
		eg:
```c
    #include“add.h”

(5)在新建源文件中要引用新建头文件

8、指针的创建

	int * p;
	p=&a;
	//等价于
	int * p = &a;

9、


	int a =10;
	int b =10;
	const int * p =&a;//常量指针 值不可以改 指向可以改
	//*p=20 错误
	//p =&b 正确
	int * const p =&a;//指针常量 值可以改  指向不能改
	//*p=20 正确
	// p=&b 错误
	const int * const p = &a;//  const修饰指针和常量 值 和指向都不能改
	//*p=20 错误
	// p=&b 错误

10、结构体数组

 struct student{
  string name;
  int age;
  int score;
};//结构体声明要写在主函数外 不然就是局部变量

结构体数组

student S1[];
s1[1].name="zhagnsan";//访问用.

结构体指针

student s;
student * p = & s;
p->name ="zhangsan";//访问用->
p->age = 18;
p->score = 100;

嵌套的结构体

struct student{
string name;
}
struct teacher{
string name;
student stu;
}
teacher.stu.name="zhangsan";

11、 string定义的字符串 可以互相“加减”对应字符

string name1="ABCDE";
string name2="A";
string name3;
name3=name2+name1[1];//name3=AA;

12、数组的删除操作 可以用覆盖
判断删除的数据位置然后依次覆盖

13、 在一个参数是指针的函数里调用一个参数是值传递的函数时,调用值传递的函数需要加上*

void deleInfo(person *p);
int locate(person p,string name);

void deleInfo(person * p)
{
	string name;
	int location;
	if (p->n_size == 0)
		cout << "记录为空" << endl;
	cout << "请输入要删除的联系人名" << endl;
	cin >> name;
	location = locate( *p, name);//此处调用要加*
	if (location == -1)
		return;
	else
	{
		for (int i = location; i < p->n_size; i++)
		{
			p->num[i] = p->num[i + 1];
		}
	}
	cout << "删除成功" << endl;

	p->n_size--;
	system("pause");
	system("cls");
	
};

14、 在头文件中的函数声明中 带结构体参数的函数声明需要加上struct!!!!!


	void menu(struct person p);//如果写void menu(person p)则不行

15、用new 和 delete 创建数组

	int *arr = new int[10];
	delete[] arr;//释放时要加上[];

16、引用必须初始化 且不能更改;
如果函数的返回值是引用类型 则可以作为左值;

		int & test();
		test()=100;
	//引用的实质是 创建一个指针常量 即
	int a=10;
	int & b= a;// 实际 编译器转化为 int * const b= &a 指针指向不能改 值可以改

17.函数重载 条件:
1、函数作用域相同(全局&局部);
2、函数名称相同;
3、函数的参数类型&顺序&个数不同;
4、函数的返回值不可以作为重载条件

	void func(;
	int funcc();//编译会报错

18、函数的默认参数,占位参数

	int func(int=10);//默认参数
	int func(int);//占位参数

19、使用类的行为时 需要在后加括号;

20、类的权限
(1)public 类内类外都可以访问 ;
(2)proteced 类内可以 类外不可以访问;区别在于继承 子类可以访问父类的 保护内容
(3)private 类内可以 类外不可以访问;子类不可以访问父类的 私有内容

21、使用引用方式传参 可以节省内存空间;

22、类的文件拆分步骤:
(1)、将类全部复制到头文件中,标题#program once 只引用一次,防止重复引用,删除所有定义和功能实现,只保留函数、变量,权限声明,,注意分号保留;

#pragma once
#include<iostream>
#include"point.h"
using namespace std;

class cirlce
{
private:
	int c_r;
	point center;

public:
	void setCP(point cen, int r);

	int getc_x();
	int getc_y();
	int getr() ;
};
(2)、将类全部复制到文件中,包含头文件,删除类的名,结构 ,只保留函数和其定义,在函数名前要加上函数的作用域,语法为:

类名 :: 函数名(表示函数作用域在类下)

#include"circle.h"
#include"point.h"

	void cirlce :: setCP(point cen, int r) {
		center = cen;
		c_r = r;
	};

	int  cirlce::getc_x() {
		return center.getx();
	};
	int  cirlce::getc_y() {
		return center.gety();
	};
	int  cirlce::getr() {
		return c_r;
	};

(3)、类嵌套定义时 只需包含已定义的头文件类即可。

23、构造函数和析构函数
构造函数和析构函数都是必须有的,没有编译器会自动帮我们加上。
构造函数:
作用:类的 初始化,即使自己不写 编译器也会写。
语法:类名(){}
注:无返回值不用void;
函数名与类名相同;
构造函数可以有参数,即可以重载;
创建对象的时候构造函数会自己调用且只调用一次。
析构函数:类的清理工作(例如释放堆的申请的空间)。
语法:~类名(){}
注:无返回值不用void;
函数名与类名相同,在名称前加~;
构造函数无参数,不可以重载;
创建对象的时候构造函数会自己调用且只调用一次。
24、构造函数分类
(1)无参(默认)构造函数,有参构造函数

	class person{
		public:
			person(){
			}//无参(默认)构造函数
			person(int a){
			}//有参构造函数 有参/无参也叫普通构造函数
			person(const person&p){
			
			}//拷贝构造函数
}
(2)调用
	void test01()
	{
		//1、括号法调用
		person p1;//默认构造的调用 调用时不要加括号,否则编译器会认为是一个函数声明
		person p2(10);//有参构造的调用
		person p3(p2);//拷贝构造调用
		//2、显示法调用
		person p1;
		person p2 = person(10);
//person(10)被称为匿名对象 执行完当前语句后 系统立即回收匿名对象
		person p3 = person(p2);
		//3、隐式转换
		person p4=10;//相当于写了p4=person(10)
		person p5=p4;//拷贝构造
}

25、拷贝构造函数使用时机
1、使用一个已经创建完毕的对象来初始化一个新对象

	person p1(20);
	person p2(p1);
2、值传递的方式给函数参数传值
void test1(person p)
{}
void test2()
{
	person p;
	test1(p);//此处调用p即调用的person的拷贝构造函数

}
3、值方式返回局部对象
	person test3()
	{
	person p1;
	return p1;//此处返回的是用拷贝构造函数创建的一个副本
}
	void test4()
	{
	person p=test3();
}

26、要是自己写了有参构造,则编译器不会提供默认构造,但会提供拷贝构造;如过自己写了拷贝构造,则编译器不会提供 默认/有参构造。

27、深拷贝与浅拷贝(难点)
浅拷贝:简单的赋值操作
浅拷贝存在的问题:堆区内存重复释放。如果利用编译器提供的拷贝构造函数,会做浅拷贝操作。解决方式用深拷贝。

class per{
	public:
		per(){
}//默认构造
		per(int age,int height){
		m_Age=age;
		m_Height = new int(height);
}//有参构造
		//自己实现拷贝构造函数 解决浅拷贝带来的问题
		per(const per &p){
		m_age=p.m_age;
		//m_height=p.m_height; 该句是编译器默认实现的浅拷贝操作
		m_height=new int(*m.height);//深拷贝操作
	}
		~per(){
		if(m_Height!=NULL)
		{
		delete m_Height;
		m_height=NULL;
		}
}//默认析构
	int age;
	int *m_Herght;
}
void test1(){
	per p1(18,160);//有参构造
	per p2(p1);//拷贝构造,且是浅拷贝,即将p1里m_Height的地址(改地址是申请的堆的地址,且在栈中,因为是局部类)直接拷贝到p2中,则析构p2时会出现再次析构p1里m_Height的地址,造成重复释放。
}
int main(){
	test1();
}

深拷贝:在堆区重新申请空间,进行拷贝操作。
28、初始化列表:通过构造函数给类中的属性赋初值
语法:类名():属性1(初值),属性2(初值)…
{}

class person{
	public:
	person(int a,int b,int c):m_a(a),m_b(b),m_c(c)
	{
}
}

27 成员初始化列表 在写构造函数的时候初始化


class person{
	public:
	person(int a,int b, int c):ma(a),mb(b),mc(c)
	{

	}
	int ma,mb,mc;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值