C++笔记(持续更新)


前言

这篇文章的知识点均来自B站的视频内容,视频链接我会放在文章最下方。记录这篇文章的目的是为了不时回头看看已经学过知识点,视频学的时候方便,但并不适合找一些零碎的,模糊的知识点。


提示:内容的提取是依照我自己已有的知识来筛选的,没有找到的话各位只能去看视频找了。

一、C++基础编程?

示例:基础编程包括指针结构体

1.指针

声明指针 [数据类型] *p = &a; (我在这想多说一嘴,这个[数据类型]要和a的数据类型一样,即等号两边的数据类型要相同)
这说明P指向a的地址,如果想访问a,就需要解引用,即*p,比如cout<< *p << endl;

常量指针
Const int *p=&a;
*p=20; //错
p=&b; //对
理由: const排前修饰int *指针叫做常量指针,这个指针的指向是可以被更改的,但指针所指的值不可以修改。

指针常量:
Int * const p = &a;
*p=20; 对
p=&b; 错
理由: const在后修饰p叫做指针常量,这个指针的指向不允许更改,但指针所指的值可以修改。

Const指针和常量都修饰:
const Int * const p = &a;
*p=20; 错
p=&b; 错
理由: const修饰既修饰指针又修饰常量,那么这个指针的指向和所指的值都不允许修改。

记忆方法
第三个应该是不用说了,我说指针常量和常量指针怎么记:实际上,函数在定义参数的时候,有时候会加"&",也就是引用,把这个加在变量前面,就变成了指针常量,也就是只能修改它的值,但不能修改它的地址,也就是不能改变指针的指向,下面一个代码块形象的展示了这个道理。

#include<iostream>
using namespace std;
void printNewValue(int &a){
    cout<<"修改前的值:"<<a<<endl;
    a = 10;
    int b=20;
    a = &b;//不注释会报错
    cout<<"修改后的值: "<<a<<endl;
}

int main(){
    int a=100;
    printNewValue(a);
    return 0;
}

结构体

结构体,我理解成是用户自定义的变量集合,里面可以自己定义想要的数据类型,灵活多变,我在这介绍结构体的三种创建方式:

struct Stuedent{
	string name;
	int age;
};
struct Stuedent{
	string name;
	int age;
}s;

上述两个结构体的创建方式其实区别很小,第二种就是最后一行多了一个"s",这表示声明了一个变量s代表这个结构体,只不过内部的变量还没被赋值。这两种方式的使用方法如下:(struct在主函数中不写也没关系)

int main()
{
	struct student s;
	s.name=”asda”;
	s.age=18;
	return 0;
}
/* 这种写法对应第二种结构
int main()
{
	s.name=”asda”;
	s.age=18;
	return 0;
}
*/
/* 这种声明方式也能起作用。
int main()
{
	struct student student s={“asda”, 18};
	return 0;
}*/

二、C++核心编程

内存分区模型

C++在执行过程中被划分为四个区域:

  1. 代码区:存放函数体的二进制代码,由操作系统管理。
  2. 全局区:存放全局变量、静态变量以及常量。
  3. 栈区:由编译器自动分配释放,存放函数的参数值,局部变量等。
  4. 堆区:由程序员分配释放,若程序员不释放,程序结束时由操作系统回收。

程序在编译后,会生成exe可执行程序,未执行该程序之前分为两个区域。

代码区:

  1. 存放CPU执行的机器指令。
  2. 代码区可共享,共享的目的是对于频繁被执行的程序,内存中有一份即可。
  3. 代码区是可读的,这样做的目的是为了防止程序意外修改了它的指令。

全局区:

  1. 存放全局变量和静态变量。
  2. 全局区还包含了常量区,字符串常量和其他常量也存放在此。
  3. 此区域的数据在程序结束后会被操作系统释放。

注意事项
栈区中,不要返回局部变量的地址,因为函数执行完局部变量就会被释放掉,拿到地址也没用,是一个非法操作。(操作的时候第一次接受返回的地址能接到是编译器做了处理,后面就接不到局部变量的地址了。)

堆区的局部变量可以返回,它是程序员指定操作的,程序(main函数)没有结束之前返回的地址都不会被操作系统清除。

new操作符

C++利用new操作符来开辟堆区的数据。这部分的数据有程序员来开辟,也 由程序员来手动释放,不手动释放的话程序结束后也会被操作系统释放掉。
开辟空间的语法是: new 数据类型。
释放的操作符是 delete, 如果是数组,则是 delete[] arr.
此外需要注意的是,new返回的是对应类型的指针,也就是值的地址,等号左边需要用指针类型。

引用

引用的操作符是&,也就是取到数据的地址。可以用在参数传递过程中,但要注意的是下面这四行代码,第三行是不合法的,如果非要简写,要写成第四行的效果,编译器会自动把你的代码优化成: int temp=10; const int & c = temp;

int a =10;
int& b = a;// 合法
//int& c = 10;// 不合法,因为引用本身需要一个合法的空间
//解决办法
const int& c = 10;

函数重载

重载也就是同一个方法的不同形式,这些形式不外乎是传入了不同类型,数量参数等。但操作的时候要注意函数重载要写在同意作用域下面。下面是几个重载的例子:

void func(){
	cout << "重载的无参调用方式" << endl;
}
void func(int a){
	cout << "重载的(int)调用方式" << a << endl;
}
void func(double a){
	cout << "重载的(double)调用方式" << a <<endl;
}
void func(int a, double b){
	cout << "重载的(int, double)调用方式" << a << b << endl;
}
void func(double a, int b){
	cout << "重载的(double , int )调用方式" << a << b << endl;
}
// 函数的返回值不可做为重载的条件
// int func(){
// }

类和对象

类的权限有三种:

  1. 公共权限 public。类内可以访问,类外也可以访问
  2. 保护权限 protected。 类内可以访问,类外不可以访问,子类可以访问基类(父类)的保护内容
  3. 私有权限 private。 类内可以访问,类外不可以访问,子类不可以访问基类(父类)的保护内容
    结构体和类的默认权限为公共权限。私有成员可以通过类内的方法改修改。

构造函数:对象创建时自动调用构造函数,可以传参。
析构函数:对象销毁前自动调用析构函数,不可传参。

构造函数调用规则

默认情况下,C++编译器至少给一个类添加三个函数(类内没有任何函数实现的时候,这三个也起作用)

  1. 默认构造函数(无参,函数体为空)
  2. 默认析构函数(无参,函数体为空)
  3. 默认拷贝构造函数,对属性进行值拷贝
    当用户自己定义了有参构造函数,C++就不提供无参构造了,但会提供拷贝构造函数。

用户如果自己定义拷贝构造函数,C++就不再提供其他的构造函数。
==注意事项:==编译器默认提供的拷贝构造是浅拷贝,当然拷贝的类型在练手一些小代码的时候不需要考虑到(但是在一些特定条件下,你想搞两个一样的类,然后修改其中一个类内部的值,诶,你会发现另外一个类内部的值也发生变化了,这时候就要考虑到是不是出现了浅拷贝)。原理上是浅拷贝仅仅是搞了个新的指针,指向原有数据的地址,然后把这个指针返回给你。现在也就是有两个指针指向同一块内存了,你不管用哪个指针来修改这块内存,内容都会改变。如何写深拷贝视频中有讲。

静态成员函数和成员变量

总结来说就是以下几点:

-静态成员变量属于整个类所有
-静态成员变量的生命期不依赖于任何对象,为程序的生命周期
-可以通过类名直接访问公有静态成员变量
-所有对象共享类的静态成员变量
-可以通过对象名访问公有静态成员变量
-静态成员变量需要在类外单独分配空间
-静态成员变量在程序内部位于全局数据区 (Type className::VarName = value)

我自己也做一些小测试:

#include<iostream>
#include<string>
using namespace std;
// 静态成员函数既不可读,也不可写正常的成员变量,只能操作静态成员变量
// 普通的成员函数可以操作静态成员变量
class TestStatic{
    public:
        int b=0;
        static int a;
        static void printValue(){
            cout << "静态成员值a为:" << a << endl;
            //cout << "静态成员值b为:" << b << endl;
        }
        static void changeValue(){
            a++;
            //b++;
        }
        //void changeValue(){
        //    a++;
        //}
};

int TestStatic::a = 10;

int main(){
    TestStatic test;
    test.printValue();
    test.changeValue();
    test.printValue();
    cout << "类名直接访问静态变量:" << TestStatic::a << endl;
    TestStatic::printValue();
    return 0;
}

输出结果如下:
在这里插入图片描述
点击链接看更详细的文章

参考

B站《黑马程序员C++教程》
C++中类的(static)静态成员变量与(static)静态成员函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值