首页 > 编程语言 >C++学习笔记

C++学习笔记

时间:2024-12-20 11:22:40浏览次数:4  
标签:const cout int age back 笔记 学习 C++ 函数


C++学习

一、基础语法:

1. 整型:

short: 2字节,1字节占8位,可表示的数据范围是-2^15~2^15-1, 第一位表示正负,所以数据范围只能是15次方 int: 4字节 long: 4字节 long long: 8字节

2. sizeof 统计数据类型(变量)所占内存的字节大小

3. 浮点型:

float: 4字节 float a = 3.14f double: 8字节

4. 字符型: char ch='a' //单引号 占一字节

5. 字符串

char str1[] = "hello world";
string str2 = "hello world";

6. 布尔: bool 占一个字节

7. 数据输入

int a = 0;
cout << "请输入a的值:" << endl;
cin >> a;
cout << "输入a的值是:" << a << endl;

8. goto 尽量不要用

9. 数组

/*定义数组*/
int arr1[1];
int arr2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int arr3[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
/*二维数组*/
int arr1[2][3];
int arr2[2][3] = {{1, 2, 3}, {4, 5, 6}};
int arr3[2][3] = {1, 2, 3, 4, 5, 6};
constexpr int size = sizeof(arr2); /*数组占用的内存空间*/
constexpr int rowSize = sizeof(arr2[0]); /*第一行占用的内存空间*/
constexpr int length = size / rowSize; /*二维数组的行数(长度)*/
cout << length << endl;

10. 函数

int add(int *p1, int &num2, int num3) {
  /*引用传值用&*/
  num2 = 10; /*num2 的值已改变*/
  *p1 = 20;
  num3 = 35;
  return 0;
}

int main() {
  int a = 10;
  int b = 20;
  int c = 30;
  add(&a, b, c);
  cout << a << endl; /*变量值改变*/
  cout << b << endl; /*变量值改变*/
  cout << c << endl; /*变量值末改变*/
}

在C++的函数参数中传递对象时是值传递,建议使用引用传递&。(但是在php中函数参数中对象的传递方式默认为引用传递)

二、核心编程:

1. 内存四区:

代码区:

全局区:全局变量、静态变量、全局常量、 程序结束后由操作系统释放

栈区:函数里的数据在栈区,不要返回局部变量的地址

堆区:new 在堆区开辟数据,int *p = new int(10),程序员管理和释放,delete

2. 引用:

int a = 10;
int &b = a;
b = 20;
cout << a << endl; // 20

3. 函数占位参数

4. 函数重载

函数名相同,参数类型不同,顺序不同 或 数量不同

5. 类和对象

class Student1 {
public:
  string name; /*姓名*/
  int num; /*学号*/
  void showDetail() const {
      cout << "姓名:" + name + ",学号:" + to_string(num) << endl;
  }
};
Student1 student1;
student1.name = "海龙";
student1.num = 10001;
student1.showDetail();

struct和class的区别:struct的默认权限是公有,class的默认权限是私有

class Person {
public:
string name;
/*构造函数*/
explicit Person(const string &name) {
this->name = name;
};
/*析构函数*/
~Person() {
cout << "Person Destructor" << endl;
};
};

C++没有对象clone方法,但是有拷贝默认构造函数,实例化时直接传入对象,可以生成新对象。

php对象作为参数的传递、赋值操作均是引用操作,因此需要使用clone方法复制对象。

初始化列表:

class Person1 {
public:
Person1(int a,int b): m_a(a), m_b(b) {
}

int m_a;
int m_b;
};
Person1 person1(10, 20);
cout << person1.m_a << endl;

静态成员变量:类内声明,类外初始化。

class Person2 {
public:
static int age;
};

int Person2::age = 12;
cout << Person2::age << endl;

静态成员函数:只可访问静态成员变量

对象的链式操作:方法返回要带*,return *this

class Person3 {
public:
explicit Person3(const int age) {
this->age = age;
}

/**
* 返回person3本身
* @param p
* @return
*/
Person3 &addAge(const Person3 &p) {
this->age += p.age;
return *this;
}

int age;
};
Person3 person3(10);
Person3 person3_1(20);
person3_1.addAge(person3).addAge(person3);
cout << person3_1.age << endl; //40

常函数:不可修改成员属性,但是用mutable修饰的成员属性可以修改。

class Person4 {
public:
explicit Person4(const int age, const int sex) {
this->age = age;
this->sex = sex;
}

void showAge() const {
// this->age = 15; const修饰的常函数,不可修改成员变量
this->sex = 1; /*mutable 修饰的成员变量可以在常函数中修改其值*/
cout << this->age << endl;
}

int age;
mutable int sex;
};
Person4 person4(18, 2);
person4.showAge();

常对象:const Person p; 不可修改成员属性,但是用mutable修饰的成员属性可以修改,常对象只能调用常函数。

友元:全局函数做友元,类做友元,成员函数做友元。

全局函数做友元:

class Building {
friend void showBuilding(Building &b);/*showBuilding 全局函数作为友元*/

public:
explicit Building() {
this->pubRoom = "客厅";
this->bedRoom = "卧室";
}

string pubRoom; /*客厅 公有*/
private:
string bedRoom; /*卧室 私有*/
};
/**
* 全局友元函数
* @param b
*/
void showBuilding(Building &b) {
cout << b.pubRoom << endl;
cout << b.bedRoom << endl; /*默认是不可以访问对象中的私有属性的,必须把该函数作为类的友元*/
}
int main() {
Building building;
showBuilding(building);
}

类做友元:

class Building {
friend class Friend;/*类做友元*/

public:
explicit Building() {
this->pubRoom = "客厅";
this->bedRoom = "卧室";
}

string pubRoom; /*客厅 公有*/
private:
string bedRoom; /*卧室 私有*/
};
/**
* 友元类
*/
class Friend {
public:
/**
* 构造函数注入build对象
*/
Friend() {
this->building = new Building();
}
Building *building;

/**
* 显示build的成员属性
*/
void showBuild() const {
cout << this->building->pubRoom << endl;
cout << this->building->bedRoom << endl;
}
};
int main() {
Friend friend01;
friend01.showBuild();
delete friend01.building;
}

成员函数做友元:

class Building;/*先声明build,便于在Friend时使用*/

class Friend {
public:
Building *building;/*引入Building作为成员属性注入,必须在前面先声明类 (循环引用)*/
Friend();
void showBuild() const;
};

class Building {
friend void Friend::showBuild() const;/*引入Friend作为友元 (循环引用)*/
public:
Building() {
this->pubRoom = "客厅";
this->bedRoom = "卧室";
}

string pubRoom; /*客厅 公有*/
private:
string bedRoom; /*卧室 私有*/
};


Friend::Friend() {
this->building = new Building;
}

void Friend::showBuild() const {
cout << this->building->pubRoom << endl;
cout << this->building->bedRoom << endl;
}
const Friend friend1;
friend1.showBuild();
delete &friend1;

运算符重载:operator+

继承:继承方式,1. public: 公众方式,2. protected: 把父类的public属性的改为protected,3. private: 私有继承,把父类的属性改为私有。

继承的方式是复制,会把父类中的成员复制到子类中,一定程度上会影响效率。

多态:虚函数:之类重写父类时要把父类函数定义为虚函数。

纯虚函数和抽象类:只要一个纯虚函数,这个类就是抽象类。虚析构,纯虚析构为了解决子类中堆区数据不能释放的问题

6. 文件操作

#include <fstream> /*包含头文件*/
/*写*/
ofstream fout;/*创建流对象*/
fout.open("D:/cpp/test.txt");/*打开文件*/
fout << "Hello World!\n";/*写数据*/
fout.close();/*关闭文件*/
/*第一种读*/
ifstream input("D:/cpp/test.txt");
string line;
while (getline(input, line)) {
cout << line << endl;
}
/*第二种读*/
ifstream ifstream;
ifstream.open("D:/cpp/test.txt", ios::in);
char buf[1024] = {0};
while (ifstream >> buf) {
cout << buf << endl;
}
/*第三种读*/
ifstream ifstream;
ifstream.open("D:/cpp/test.txt", ios::in);
char buf[1024] = {0};
while (ifstream.getline(buf, sizeof(buf))) {
cout << buf << endl;
}
/*第四种读*/
ifstream ifstream;
ifstream.open("D:/cpp/test.txt", ios::in);
string buf;
while (getline(ifstream, buf)) {
cout << buf << endl;
}

二进制写入文件

#include <fstream> /*包含头文件*/
class Person {
public:
char m_name[20];
int age;
};
ofstream fout;
fout.open("person.txt", ios::out | ios::binary); /*二进制 写的方式打开文件*/
if (!fout.is_open()) {
cout << "Can't open file";
return 1;
}
Person p = {"张三", 18};
fout.write(reinterpret_cast<const char *>(&p), sizeof(Person));
fout.close();

二进制读文件

#include <fstream> /*包含头文件*/
class Person {
public:
char m_name[20];
int age;
};
ifstream ifs;
ifs.open("person.txt", ios::in | ios::binary);/*以二进制只读方式打开*/
if (!ifs.is_open()) {
cout << "Error opening file" << endl;
return 0;
}
Person p{};
ifs.read(reinterpret_cast<char *>(&p), sizeof(Person));
cout << "Name: " << p.m_name << endl;
cout << "Age: " << p.age << endl;
ifs.close();

三、高级编辑

1. 模板:泛型编程、STL。

函数模板:如果函数模板和普通函数同时存在,优先调用普通函数;可以强制调用函数模板;函数模样也可以重载;如果有更好的配置,则优先调用函数模板(如普通函数的参数是int,传的参数是char,则优先调用函数模板);函数模板和普通函数尽量不要同时出现。

/**
* 声明一个模板
* @tparam T
* @return
*/
template<typename T>
void mySwap(T &a, T &b) {
T temp = a;
a = b;
b = temp;
}
int a = 10;
int b = 20;
mySwap(a,b);/*自动推导数据类型:a 20 b 10*/
string s = "hello";
string s1 = "world";
mySwap<string>(s,s1);/*指定数据类型(建议):string world hello*/

类模板:

/*类模板*/
template<class NameType, class AgeType>
class PersonX {
public:
PersonX(NameType name, AgeType age) {
this->name = name;
this->age = age;
}

NameType name;
AgeType age;
};

int main() {
PersonX<string, int> p1("John", 10);
PersonX<int, string> p2(7758, "15");
cout << p1.name << "_" << p1.age << endl;
cout << p2.name << "_" << p2.age << endl;
}

类模板与函数模板的区别:类模板不能自动推导数据类型,类模板可以设置默认数据类型而函数模板不可以。

2. STL: Standard Template Library 标准模板库:

容器、算法、迭代器(容器和算法之能通过迭代器进行无缝连接):string、vector(读数组快)、deque(写数组快)、stack(栈容器)、queue、list、set、map等容器

vector:类似数组(头插数据要整体移动数据,适合做只读数据):empty()、resize(10)、size()数组中的个数、capacity()数组中的容量、push_back()、insert()、erase()、clear()、back()、front()等方法,shrink_to_fit():释放多余内存,reserve():预留空间

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int main() {
vector<int> v;
v.push_back(1);
v.push_back(2);
auto itBegin = v.begin();/*起始迭代器 1*/
const auto itEnd = v.end();/*结束迭代器 6619472*/
/*遍历1*/
while (itBegin != itEnd) {
cout << *itBegin << endl;
++itBegin;
}
/*遍历2*/
for (const int & it : v) {
cout << it << endl;
}
/*遍历3*/
ranges::for_each(v, [](const int &it) {
cout << it << endl;
});
return 0;
}

vector预留空间:v1.reserve(100000);

void test01() {
vector<int> v1;
const int *p = nullptr; /*v1 的首地址*/
int num = 0; /*动态开辟内存的次数*/
// v1.reserve(100000);
for (int i = 0; i < 100000; i++) {
v1.push_back(i);
if (p != &v1[0]) {
/*开辟一次内存*/
p = &v1[0];
num++;
}
}
cout << v1.size() << endl;/*100000*/
cout << v1.capacity() << endl;/*131072*/
cout << num << endl; /*18:存放100000个数字要开辟内存18次,解决办法是使用*/
}

int main() {
test01();
return 0;
}

deque容器:双端数组,适合做多端插入和删除。push_back、push_front、pop_back、pop_front、insert

list容器:双向循环链表,front、back、push_back、push_front、pop_front、pop_back、insert、resize、assign、empty、size、remove(删除指定值的元素)、sort、reverse、erase、clear。

list<int> l;
l.push_back(10);
l.push_back(20);
l.push_back(30);
l.push_back(40);
l.push_front(50);
l.sort([&](const int a, const int b) { return a > b; }); // 降序排序

set/multiset容器:集合,底层是二叉树,set不允许有重复元素。empty、insert、swap、clear、erase、find、count。

set<int> s1;
if (auto [fst, snd] = s1.insert(10); snd == true) {
cout<<"插入成功"<<endl;
}else {
cout<<"插入失败"<<endl;
}
if (auto [fst, snd] = s1.insert(10); snd == true) {
cout<<"插入成功"<<endl;
}else {
cout<<"插入失败"<<endl;
}
s1.insert(20);
//设置set排序为降序
set<int,greater<>> s;
s.insert(10);
s.insert(40);
s.insert(20);
s.insert(30);
/*40 30 20 10*/
for (const int it : s) {
cout << it << endl;
}
// 自定义数据类型 使用仿函数排序
class Human {
public:
explicit Human(string name, const int age, const int height) {
this->name = std::move(name);
this->age = age;
this->height = height;
}

bool operator<(const Human& rhs) const {
return this->age > rhs.age;
}
string name;
int age;
int height;
};
const Human h1("Tom", 12, 160);
const Human h2("David", 20, 172);
const Human h3("Steff", 20, 168);
const Human h4("Human", 15, 169);
const Human h5("HaiMei", 20, 188);
multiset<Human> set1;
set1.insert(h1);
set1.insert(h2);
set1.insert(h3);
set1.insert(h4);
set1.insert(h5);
for (const Human& it : set1) {
cout << it.age << endl;
}

pair对组:

pair<string, int> p("Tom", 24);
cout << p.first << p.second << endl; //Tom 24

map/multimap容器:高效率,高性能,key、value格式,会按key值默认排序。size、empty、swap、insert、clear、erase(key)、count(key)、find(key)

map<int, int> m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
m.insert(pair<int, int>(4, 40));
if (const auto it = m.find(3); it != m.end()) {
cout << "查找到数据了" << endl;
} else {
cout << "没查找到数据" << endl;
}
for (auto & it : m) {
cout << it.second << endl;
}

3. 函数对象(仿函数)

class myAdd {
public:
// 重载操作符 ()
int operator()(const int a, const int b) const {
return a + b;
}
};
constexpr myAdd add;
cout << add(1, 3) << endl; // 你调用函数一样调用类中的重载操作符

谓词:返回类型是bool类型的仿函数是谓词。一元谓词、二元谓词,(直接使用回调函数方便些)

vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
/*查找大于5的数字*/
auto it = find_if(v.begin(), v.end(), [](const int i) { return i >5; });
if (it == v.end()) {
cout << "没有找到" << endl;
} else {
cout << "找到" << endl;
}

内建函数对象:negate(取反)、plus(加法)、

#include <functional>
negate<int> n; /*取反*/
cout << n(50) << endl;/*-50*/
plus<int> plus; /*相加*/
cout << plus(10, 20) << endl; /*30*/

4. 常用算法:

for_each、transform、find、find_if、adjacent_fin、binary_search(二分查找,必须是有序的序列)、count、count_if、sort、random_shuffle(洗牌)、merge(两个序列必须是有序的)、reverse、copy、replace、replace_if、swap、accumulate(累加)、fill

(*注意返回值大部分是迭代器)

class Hum {
public:
Hum(string name, const int age) {
this->name = std::move(name);
this->age = age;
}

string name;
int age;
};

int main() {
vector<Hum> hums;
hums.emplace_back("John", 20);
hums.emplace_back("Marvine", 30);
hums.emplace_back("David", 40);
hums.emplace_back("Staff", 50);
// 条件查找
if (const auto it = find_if(hums.begin(), hums.end(), [](const Hum &hum) { return hum.age > 30; });
it != hums.end()) {
cout << "找到大于30岁的人了," << it->name << endl;/*David*/
}
}
vector<Hum> hums;
hums.emplace_back("John", 30);
hums.emplace_back("Jane", 20);
hums.emplace_back("Dvid", 40);
for (auto &hum: hums) {
cout << hum.name << " " << hum.age << endl;
}
cout << "-----------"<< endl;
// 大于30岁的替换成新的
ranges::replace_if(hums, [](const Hum &h) {return h.age>20;},Hum("xxx", 100));
for (auto &hum: hums) {
cout << hum.name << " " << hum.age << endl;
}

常用集合算法:set_intersection(求两个容器的交集)、set_union(并集)、difference(差集)

标签:const,cout,int,age,back,笔记,学习,C++,函数
From: https://www.cnblogs.com/longfeiPHP/p/18618942

相关文章

  • Vue学习
    基础js代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Document</title......
  • 2024-2025-1 20241328 《计算机基础与程序设计》第十三周学习总结
    2024-2025-120241328《计算机基础与程序设计》第十三周学习总结作业信息作业课程2024-2025-1-计算机基础与程序设计作业要求2024-2025-1计算机基础与程序设计第十三周作业作业目标无教材学习内容总结《C语言程序设计》第12章知识点总结12.1文件的基本概......
  • Makefile简单学习
    Makefile简单学习什么是Makefile?一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也......
  • 【Java学习笔记】多线程基础
    并行:同一时刻,多任务同时进行多任务分别进行一、线程相关概念1.程序是为完成特定任务、用某种语言编写的一组指令的集合。简单的说:就是我们写的代码2.进程(1)进程指的就是运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当我们使用迅......
  • 2024-2025-1 20241305 《计算机基础和程序设计》第十三周学习总结
    作业信息这个作业属于哪个课程2024-2025-1-计算机基础与程序设计](https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP)这个作业要求在哪里2024-2025-1计算机基础与程序设计第十三周作业这个作业的目标《C语言程序设计》第12章并完成云班课测试作业正文本......
  • PAWNYABLE kernel userfaultfd 笔记
    感觉这个是比较古老(2020左右的)用法了,看看即可?概念userfaultfd可以类比成一个缺页异常的handler,如果handler可以处理很久,那可能更好达到竞争的效果工作流程参考KernelPwnSyscalluserfaultfdandSyscallsetxattr-Wings的博客户通过userfaultfd系统调用接收文件描......
  • 深度可分离卷积原理分析回顾、代码实践与优缺点对比学习记录
    最近在项目开发中有需要用到轻量化相关的内容,那必定是绕不开深度可分离卷积的,这里记录自己的学习记录和实践内容。深度可分离卷积(DepthwiseSeparableConvolution)是一种轻量化的卷积操作,广泛应用于移动设备和嵌入式设备上的深度学习模型(如MobileNet和Xception)。它将标准......
  • Java学习,数组中查找指定元素
    Java中查找数组中的指定元素是一个常见的操作。数组中查找指定的元素,并返索引:publicclassFindElementInArray{  publicstaticvoidmain(String[]args){    int[]numbers={10,20,30,40,50};    inttarget=30;    intindex......
  • Java学习,数组是否相等
    Java中判断两个数组是否相等,不是直接的事情,数组对象之间的 equals()方法,并不会逐个比较数组元素,是比较数组对象的引用是否相同(即它们是否指向内存中同一个位置)。要判断两个数组,是否包含相同的元素并且顺序也相同。判断两个整数数组是否相等publicclassArrayEqualityChecke......
  • 【机器学习】数据分析之Pandas(一)
    pandas数据分析库第一部分介绍Python在数据处理和准备方面一直做得很好,但在数据分析和建模方面就差一些。pandas帮助填补了这一空白,使您能够在Python中执行整个数据分析工作流程,而不必切换到更特定于领域的语言,如R。与出色的jupyter工具包和其他库相结合,Python中用于进......