当前位置: 首页 > article >正文

C++知识框架

简介

起源:贝尔实验室20世纪80年代。C也是贝尔实验室的研究员丹尼斯·里奇。

应用范围:操作系统、编译器、文字处理程序、大型游戏。

C++ vs C:C是结构化和模块化的语言。C++增加了面向对象的机制(俗称"带类的C")。

语法

数据类型

//x64处理器 64位window10 vs2015 
#include <iostream>
using namespace std;	// 没有此,则cout 时,需要写成 std::cout
int main()
{	
    /*
    cout:字符输出流对象
    << 是输出运算符
    endl 是用于输出换行并刷新缓冲区
    */
	cout << sizeof(bool) <<  endl;	
	cout << sizeof(char)<<" " << sizeof(short)<<" "<< sizeof(signed int) << " " << sizeof(long) << " " << sizeof(signed long long) << " " << sizeof(float) << " " << sizeof(double) << " " << sizeof(float) << " " << sizeof(long double) << endl;
	cout <<sizeof(unsigned char)<<" "<< sizeof(unsigned short) << " " << sizeof(unsigned int) << " " << sizeof(unsigned long) << " " << sizeof(unsigned long long) << endl;
	cout << sizeof(unsigned) << endl;

	system("pause");
	return 0;
}


// 输出
1
1 2 4 4 8 4 8 4 16
1 2 4 4 8
4

typedef声明:

typedef int myint; // 后面直接可以使用myint num = 123;

枚举

enum course {
    chinese,
    math,
    english
}; 

int main()
{
    course c = math;
    cout << c << endl;		// 输出:1
	return 0;
}

结构体

// Demo1: struct定义结构体
struct person
{
    int year;
    int age;
    string name;
}p1 = {2024, 24, "adair"}, p2 = {2025, 25, "adair2"};
int main()
{
    struct person p3 = {2026, 26, "adair3"};
    cout << p1.name << endl;
    cout << p3.name << endl;
}


// Demo1: 结构体数组
struct person
{
	int year;
	int age;
	string name;
}p[2] ={ {2024, 24, "adair"}, {2025, 25, "adair2"}};//可以不指定数组元素个数
p[1].age;

结构体对齐

// 默认指定对齐值=8
struct st1
{
	// 空结构体大小1
	char c1;//1 
	char c2;//2
	int i1;//8  由于出现int(4个字节),下面都是4的整数
	char c3;//12
	short s4;//12
	double d;//24 由于出现double(8个字节),下面都是8的整数
	char c4;//32   
	int i2;//32  28+4 = 32
	int i3;//40   
	short s5;//40
};

//指定对齐值=4
#pragma  pack(4)
struct st2
{
	//1 空结构体大小1
	char c1;//1
	char c2;//2
	int i1;//8
	char c3;//12
	short s4;//12
	double d;//20
	char c4;//24
	int i2;//28
	int i3;//32
	short s5;//36
};

int main()
{
    cout << sizeof(st1) << endl;//40
    cout << sizeof(st2) << endl;//36
}
image-20241218152208915

共用体

union data {
    
    char c;
    int i;
    float f;
}x = {.f = 1.1234};		// 初始化
int main()
{
    data y = {'A'};		// 初始化
    cout << x.f << endl;

    // 存储是二进制相同,区别就是如何解释。
    cout << y.i << endl;
    cout << y.c << endl;
    cout << y.f << endl;
}

变量

// 变量声明
extern int a, b;
int main ()
{
  // 变量定义
  int a, b;
  // 初始化
  a = 23;
  b = 25;
  return 0;
}

变量的作用域

// demo1: 局部变量和全局变量相同,函数内使用局部的值。
int i = 66;
int main ()
{
  int i = 88;
  cout << i << endl;//	88
  cout << ::i << endl;	//	66
  return 0;
}


// demo2: 全局变量为初始化时,int/float/double自动为0, char为'\0',指针为NULL
int i;
float f;
double d;
char c;	// c默认为'\0'所以不会输出
int *p;
int main()
{
	cout << i << f << d << "c=" << c << "p=" << p << endl;//000c=p=0
	return 0;
}

运算符

int d = ~234;     // d = -235。~n=-n-1

//	赋值运算符:+= -= *= /= %= <<= >>= &= ^= !=

数组

int array[5]= {2, 3, 4, 5, 6};	// array常量指针
,auto 类型也是 C++11 新标准中的,用来自动获取变量的类型
// 遍历
for(auto x : array){   // int 也可以改为 auto 
    cout << x << endl;
}
cout << *(array+2) << endl;		// 输出:4
cout << sizeof(array) / sizeof(array[0]) << endl; // 总个数
cout << end(array) - begin(array) << endl;	// 同上
/* 如果直接打印end(array)和begin(array) ,则差值为 个数*sizeof(type_t)*/


int arr1[4] = {1,2,3,4};
int arr2[4] = { 1,2 };	// 等效于1,2,0,0
int arr[4] = {0};//所有元素为0

二维数组

// Demo1: 数组和地址
int arr1[2][3];
int arr[2][3] = {0};//所有元素为0
int arr2[2][3] = { {1,2,3},{4,5,6} };
int arr3[2][3] = { 1,2,3 ,4,5,6 };
int arr4[2][3] = { {1},{4,6} };
int arr5[][3] = { 1,2,3 ,4,5,6 };

// 获取行数和列数和总个数
int rows = sizeof(arr) / sizeof(arr[0]);
int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
int sum = sizeof(arr) / sizeof(arr[0][0]);


// 获取指向数组首元素的指针
int* ptr = (int*)arr2;
cout << "arr2[0][0] = " <<  *ptr << endl;   // 等效于 **arr2
cout << "arr2[0][1] = " <<  *(ptr + 1) << endl; // 等效于 *(*arr2 + 1)即arr+n*sizeof(type_t)。
cout << "arr2[1][0] = " <<  *(ptr + 3) << endl; // 等效于 *(*arr2 + 3)

cout << "arr2 = " << *(*arr2 + 1) << endl;      // 输出:2
cout << "arr2 = " << **(arr2+1) << endl;        // 输出:4

/*	二维数组:
	*arr表示第一行数组指针arr[0]
	*(arr+1)表示第二行数组指针arr[1]
	*(*(arr+i)+j) 表示a[i][j]。等效*(arr[i] + j)
	*(*arr+n) 表示arr数组的第n+1个值
	arr[i] == &arr[i][0] 
	
	一维数组:
	int *p1 = arr;  // 等效 &arr[0];
	cout << *p1 << endl;
	
*/



// Demo2: 二维数组指针赋值
int a[2][3] = { {1,2,3},{4,5,6} };
int (*ap)[3];
ap = a;
cout << *(*(ap+1)+1) << endl;


// 二维数组遍历,双层for

数组和new(动态创建数组)

int* arr1 = new int[2];     //delete []arr1;
int* arr2 = new int[2] {1, 2};


// demo1: new创建二维数组
int rows = 3, cols = 2;
int** arr = new int*[rows];
for (size_t i = 0; i < rows; i++)
{
    arr[i] = new int[cols]
}
// 依次赋值即可...
arr3[0][1] = 1;
// 释放内存
for (int i = 0; i < m; ++i) {
    delete[] arr[i];  // 释放每行的内存
}
delete[] arr;  // 释放指针数组



// demo2: 一维数组模拟二维数组
int* arr4 = new int[2 * 3];
// 依次赋值即可...
arr4[0] = 1;    // arr4[i * n + j] 可以遍历
// 释放内存
delete[] arr4;  // 释放整个一维数组



数组与函数:

如果传递二维数组,形参必须制定第二维的长度。

条件编译

#ifdef Identifier   // 亦可#ifndef Identifier 
    program1
#else
    program2
#endif


#if express   // express为true则执行program1
    program1
#else
    program2
#endif

指针

// 指针和二维数组:在前面说过。

// Demo1: 指针和函数
#include <iostream>

int* getLocalVariable() {
    int localVar = 42;  // 普通局部变量
    return &localVar;   // 返回局部变量的地址,这是不安全的,会
}

int main() {
    int* ptr = getLocalVariable();  // 这里会出错
    std::cout << *ptr << std::endl; // 访问野指针(悬空指针),未定义行为
    return 0;
}
// 解决方法:static int localVar = 42; 


// Demo2: p+n(指针运算)得到的地址是p+n*sizeof(type_t)。
int arr[5] = {1, 2, 3, 4, 5};
int *p1 = &arr[1];
int *p2 = &arr[3];
cout << p2 - p1 << endl;    // 输出:2。可以反知:p2 = p1 + 2;


// Demo3: new 和 delete
int* p = new int(2);    // 赋值
cout << *p << endl;
delete p;  

int* arrp = new int[10];
for (size_t i = 0; i < 10; i++) {
    arrp[i] = i;
}
cout << arrp[7] << endl;
delete[] arrp;  //释放为多个变量分配的地址

引用&

// Demo1: 变量引用
int a = 10;
int &b = a;	//a和b表示相同的变量,具有相同的地址。

// Demo2: 函数引用。可以修改实参。
int add1(int &r) {		
	r += 1;
	return r;
}

// 错误:返回的是局部变量
int add1(int &r) {
	r += 1;
	int res = r;
	return res;
}

无论什么指针,最后都要delete释放内存。

函数

// Demo1: 使用函数,修改传递过来的实参
int add(int& value){	// 使用&(引用)、*(地址)可以改变传过来的v。直接使用v则不改变。
    return ++value;
}

int main ()
{   
    int v = 1;
    cout << add(v) << endl;
    cout << v << endl;
    return 0;
}


// Demo2: 参数默认值
int add(int value, int count = 2){
    return value + count;
}
int main ()
{   
    int v = 1;
    cout << add(v) << endl;
    return 0;
}

// Demo3: 函数指针
void add1(int &x) {
    x += 1;
}
int main()
{
    int num = 2;
	void (*funcPtr)(int &) = &add1;
    funcPtr(num);
    cout << num << endl;    // 输出:3

}

函数重载

// 均为重载函数
int add(int a,int b)
{
	return a+b;
}

int add(int a,int b,int c)
{
	return a+b+c;
}
double add(double a,double b)	
{
	return a+b;
}

// 反例(不是重载函数)。只有返回类型不同,则不是重载函数
double add(int a,int b)
{
	return a+b;
}

内联函数

用内联函数替换,所以不发生函数调用,不需要保护现场,恢复现场,节省了开销。

// 可以使用汇编看add()是否发生call,如果有call则说明inline模式不成功
inline int add(int a, int b) {
    return a + b;
}
int main ()
{   
    cout << add(1, 4) << endl;
    return 0;
}
// 如果内联函数过于复杂(比如双层for循环),编译器就把内联函数当做普通函数看待了

字符串

C的格式:

// C的字符串就是字符数组,最后一位是'\0'。
char str[7] = {'h','e','i','r','e','e','\0'};
// 也可以使用 双引号代替数组
char str2[] = "abc";	
// 使用指针代替,
char* strptr = "abc";
cout << str << endl;
cin >> str;			// 修改str的值
cout << str << endl;


// 常用函数
strcat(char s1[],const char s2[]);//将s2接到s1上
strcpy(char s1[],const char s2[]);//将s2复制到s1上
strcmp(const char s1[],const char s2[]);//比较s1,s2 s1>s2返回1 相等返回1,否则返回-1
strlen(char s[]);//计算字符串s的长度 字符串s的实际长度,不包括\0在内

C++格式

// 使用string对象
string str = "Shanghai" ;
cout << str << endl;
str[5] = 'H';   // 修改某位字符
cout << str << endl;


// 字符串数组
string arr[3] = {"abc", "xyz", "123"};
cout << arr[0] << endl;

// 常用函数
string str = "Shanghai" ;
cout << str.size() << endl;
str.insert(5,"Hello");  // 插入 
str.append("aaa");  // 追加
str += "bbb";       // 追加
// str.erase(1,3);
str.replace(3, 2 ,"bbb");
cout << str.find("bbb") << endl;    // 反向查找 str.rfind()
cout << str.find_first_of("aeiou") << endl;      // 查找第一个元音字母

cout << str << endl;

// 字符串遍历1: str.size() for循环下标

// 字符串遍历2: 正向迭代器
for (string::iterator iter = str.begin(); iter < str.end(); iter++)
{
    cout << *iter;
}
cout << endl;
// 字符串遍历3: 反向迭代器
for (string::reverse_iterator riter = str.rbegin(); riter < str.rend(); riter++)
{
    cout << *riter;
}

字符串分割:

char str[] = "I,am,a,student; hello world!";
const char *split = ",; !";
char *p2 = strtok(str, split);
while (p2 != NULL)
{
    cout << p2 << endl;
    p2 = strtok(NULL, split);  // 继续分割
}

字符串之间的区别

// C 和 C++ 在此都是一样的
// str 数组会被分配在栈上,并且包含所有的字符,包括字符串的结束符 \0。可以修改数组中的字符。
char str[] = "I,am,a,student; hello world!";
str[0] = 'i';  // 可以修改

// 字符串常量存储在 只读内存区。不可以修改字符串
char* str = "I,am,a,student; hello world!";

// 如果const char* str:更加表明不可修改。

域运算符

// Demo1: 访问类的静态成员函数、静态变量
class MyClass {
public:
    static int staticVar;
    static void staticFunction() {
        cout << "This is staticFunction" << endl;
    }
    
};
// 静态成员变量需要使用双冒号访问
int MyClass::staticVar = 10;
int main() {
    // 通过类名和作用域解析运算符访问静态成员
    cout << MyClass::staticVar << endl;
    MyClass::staticFunction();
    return 0;
}




// Demo2: 访问命名空间中的函数、类、变量等成员。
// 定义命名空间
namespace MyClass {
    int var = 10;   
    void func() {  
        cout << "This is func" << endl;
    }    
};
int main() {
    // 访问命名空间中的成员
    cout << MyClass::var << endl;
    MyClass::func();
    return 0;
}




// Demo3: 访问全局变量
int var = 1;
int main() {
    int var = 2;
    cout << ::var << endl;
    return 0;
}




// Demo4: 类外定义函数
class MyClass {
public:
    void display();
};
// 类外定义成员函数时使用双冒号
void MyClass::display() {
    cout << "This is display" << endl;
}
int main() {
    MyClass obj;
    obj.display();
    return 0;
}




// Demo5: 访问嵌套类
class Outer {
public:
    class Inner {
        public:
            void display(){
                cout << "Outer -> Inner -> dispaly()" << endl;
            }
    };
};
int main() {
    Outer::Inner obj;
    obj.display();  // 通过作用域解析访问嵌套类
    return 0;
}

类也是一种数据类型。

// 类的声明
class 类名
{
	public:			// 权限:类外均可访问
		公有数据成员;
		公有成员函数;
	private:		// 权限:只有类内进行访问
		私有数据成员;
		私有成员函数;
	protected:		// 权限:类内和派生类可以访问
		保护数据成员;
		保护成员函数;
};

// 成员函数的定义
返回类型 类名:成员函数名(参数列表)	// 类外定义
{
	函数体;
}
inline 返回类型 类名:成员函数名(参数列表)	// 类外定义(内联函数)
{
	函数体;
}

类的实例化

class Person {
public:
    int age;
    string name;
    // 构造器
    Person(int age, string name) : age(age), name(name){
    }
    // 空构造器。如果没有构造器,默认会有一个空构造器
    Person(){}
};

int main()
{
    Person* p1 = new Person(10, "Alice");	// 使用指针
    Person p2(11, "Bob");		// 使用构造器

    Person p3;      // 使用空构造器
    p3.age = 12;
    p3.name = "Tom";

    cout << p1->age << endl;
    cout << p2.name << endl;
    cout << p3.name << endl;
    cout << p4->name << endl;
}

类的函数实现

class Person {
public:
    // 默认参数
    Person(int = 0, string = "zhangsan");
    Person(Person& p);  // 拷贝构造函数
    void show();
private:
    int age;
    string name;

};
Person::Person(int i, string str){
    age = i;
    name = str;
}
Person::Person(Person& p) {
    age = p.age;
    name = p.name;
}
void Person::show(){
    cout << "age = " << age << ",name =" << name << endl;
}


int main()
{
    Person p1;
    Person p2(12);
    Person p3(13, "lisi");
    Person p4(p3);  

    p1.show();
    p2.show();
    p3.show();
    p4.show();
    return 0;
}

析构函数

#include <iostream>

using namespace std;


class Person {
public:
    /* 如果去掉const报错:
        字符串字面量(例如 "adair")本质上是常量字符数组,为 const char[] 类型
        如果绑定到一个非常量的引用类型(如 string&),破坏常量数据的不可修改性。

        使用 const string& 是OK,因为编译器保证你不会修改引用的内容。
    */
    Person(const string& name){
        this->name = new string(name);
        cout << "Construct..." << endl;
    }
    // 析构函数: 函数名 = 类名,无参无返回
    ~Person(){
        delete name;
        cout << "Destroyed..." << endl;
    }

    // const表示不会修改对象的任何成员变量(mutable 除外)
    void show() const{
        cout << "name = " << *name << endl; 
    }
private:
    string* name;
};

int main()
{
    Person p("adair");
    p.show();
    return 0;
}

函数指针

Person p("adair");
void (Person::*pfun)() = &Person::show;
(p.*pfun)();	// 等效,p.show();

类中还有this指针

// 在类的定义中
this->age;

静态成员

class MyClass {
    static int count;
    static void show() {
        cout << count << endl;
    }
}
int main() {
    MyClass::count = 1;
    MyClass::show();
    
    MyClass obj;
    obj
}

友元函数

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val){}

    // 友元函数
    friend void show(const MyClass& obj);

};

void show(const MyClass& obj) {
    // 可以访问类的private
    cout << obj.data << endl;
}


int main() {
    MyClass obj(3);
    show(obj);

    return 0;
}

类和结构体:

  • C++引入结构体,是为了兼容C。C中空结构体sizeof(type_t)为0,而C++空结构体为1.
  • C++结构体中可以定义函数
  • C++结构体默认public,类中默认private
struct Person {
    int age;
    string name;
    void show() {
        cout << age << endl;
    }
};


int main() {
    // 如果Person改为class,则不可以访问。
    struct Person p;
    p.age = 2;
    p.name = "adair";
    p.show(); 	
}

继承

继承方式 / 基类成员public成员protected成员private成员
publicpubliceprotected不可见
protectedprotectedprotected不可见
privateprivateprivate不可见

子类修改基类的范围

class Base{
public:
    void show(){};
protected:
    int a;
    int b;
};

class Person:public Base {
public:
    using Base::a;  // 让base类的protected变成public
    using Base::b;
private:
    using Base::show;
    string name;
};

int main() {
    Person *p = new Person();
    p->a = 1;       // 如果没有修改范围,报错
    p->b = 2;

    // show()不可以访问

    delete p;
    return 0;    

}

// Demo2: 派生类 转为 基类
class A {
public:
    int a;
};
class B : public A {
public:
    int b;
};

int main() {   
    B *b;
    b->a = 1;
    b->b = 2;
    A* a = (A*)b;   // 无论是指针还是对象,都会损失变量b.b.
    return 0;    
}

继承中构造器和析构函数。

class Base{
private:
    int a;
    int b;
public:
    Base(int, int);
    ~Base();
};
Base::Base(int val1, int val2) : a(val1) , b(val2){
    cout << "Base constructor..." << endl;
}
Base::~Base(){
    cout << "Base destroy..." << endl;
}

class Person : public Base {
public:
    Person(int, int, string);
    ~Person();
private:
    string name;
};			// 类后面要带`;`


Person::Person(int a, int b, string str) : Base(a, b), name(str){
    cout << "Person constructor..." << endl;
}
Person::~Person(){
    cout << "Person destroy..." << endl;
}

int main() {
    cout << "Create..." << endl;
    Person *p = new Person(1, 2, "adair");    
    cout << "Delete..." << endl;
    delete p;
    return 0;    

}
// 输出
Create...
Base constructor...
Person constructor...
Delete...
Person destroy...
Base destroy...

多继承

// Demo1: 基本多继承
class A {
public:
    void eat(){
    }
};
class B {
public:
    void sleep(){
    }
};

class C : public A, public B {
public:
    void run(){
    }
};

int main() {   
    C c;
    // 均为正确调用
    c.eat();
    c.sleep();
    c.run();
    return 0;  
}


// Demo2: 两个基类有同样的方法
class A {
public:
    void sleep(){
    }
};
class B {
public:
    void sleep(){
    }
};

class C : public A, public B {
public:    
    void run(){   
        // 解决歧义问题:如果c.sleep()则会报错,因此直接使用run()代替
        A::sleep();
        B::sleep();
    }
};


// Demo3: 虚基类
class A {
public:
    int a;
};
class B : virtual public A {
public:
    int b;
};
class C : virtual public A {
public:
    int c;
};
class D : public B, public C {
public:
    int d;
};

int main() {   
    D d;
    // 均为正确调用
    d.a = 1;
    d.b = 1;
    d.c = 1;
    d.d = 1;
    return 0;   
}
/*
	如果B类中再声明int a;则d.a访问的就是B中的a;
	如果B类和C类同时再次定义a,则歧义。
*/

虚函数

// Demo1: 虚函数
class A {
public:
    virtual void show(){
        cout << "A show" << endl;
    }
};
class B : public A {
public:
    void show(){
        cout << "B show" << endl;
    }
};


int main() {   
    B b;
    b.show();   // B show
    A* a = &b;
    a->show();  // B show,如果没有virtual,则为A show

    A aa = (A)b;
    aa.show();  // A show
    return 0;    
}


// Demo2: 纯虚函数。
class  A	// A中的方法就相当于接口
{
public:
	virtual void show() = 0;
};
class B:  public A
{
public:
	void show()
	{
		cout << "B show" << endl;
	}
};



重载

// Demo1: 减号重载
class Point {
private:
    int x, y;
public:

    Point(int x = 0, int y = 0) : x(x), y(y) {}
    Point operator+ (const Point& p){   // 重载 -、*、/、自增、自减...
        return Point(x + p.x, y + p.y);
    }
    void show() {
        cout << "x = " << x << ", y = " << y << endl; 
    }
    Point operator++(){ 
        (this->x)++;
        (this->y)++;
        return *this;
    }
};
int main(){
    Point p1(1, 2);
    Point p2(3, 4);
    Point p3 = p1 + p2;
    // 等效p1.operator+(p2).show();
    p3.show();
    // 等效p1.operator++().show();
    (++p1).show();  
    return 0;
}

// Demo2:  自增/自减:前置 or 后置
class Point {
private:
    int x, y;
public:
    Point(int x = 0, int y = 0) : x(x), y(y) {}
    // 前置自增
    Point& operator++(){    // 返回的是引用,因为需要修改值
        x++;
        y++;
        return *this;
    }
    // 后置自增
    Point operator++(int){    // 返回的是对象,因为无需要修改值
        Point temp = *this;
        ++(*this);      // 调用前置自增
        return temp;
    }
    void print() const {
        cout << "x = " << x << ",y = " << y << endl;
    }
};

int main(){
    Point p1(1, 2);
    p1.print();     //  1, 2

    p1++;
    p1.print();     //  2, 3

    Point p2 = p1++;
    p2.print();     //  2, 3
    p1.print();     //  3, 4   

    return 0;
}



// Demo3: 字符串重载
class String {
public:
    string str;
    /*	const string& str 优于 const string str
    	 const string str:会进行拷贝副本,为局部变量。
    	 const string& str:不拷贝,直接用指针,高效,const又表明不会修改其值
    */
    String(const string& str) : str(str) {} 

    // 赋值运算符重载
    String& operator=(const String &s);
};

String& String::operator=(const String &s)
{
    if (this != &s) { // 防止自我赋值
        str = s.str; // 直接使用 string 类的赋值运算符
    }
    return *this;
}

int main() {
    String s1("hello"); // 使用 string 直接构造
    String s2("123");
    s2 = s1; // 使用赋值运算符
    cout << s2.str << endl; // 输出 hello

    string s3;


    return 0;
}


// Demo4: 类型转化
class A {
private:
    int x, y;
public:
    A(int x, int y) : x(x), y(y) {}
    operator int(){
        return x + y;
    }

};

int main() {
    A a(3, 4);
    int num = a;
    cout << num << endl;    // 7
    return 0;
}

IO流(IOS)

输入流、输出流都是对于内存来说的。内存缓冲区用来存放流的数据。

分类:

  • iostream:istream,ostream,iostream
  • fstream:ifstream,ofstream,fstream
  • strstream:istrstream,ostrstream,strstream

tip:

  • cin 就是该类istream的对象。cout 就是该类ostream的对象。
  • cerr 不使用缓冲区,直接向显示器输出信息;而输出到 clog 中的信息会先被存放到缓冲区,缓冲区满或者刷新时才输出到屏幕。
// Demo1: 循环读取键盘值
char c; // 通过c = cin.get();读取键盘上的一个字符
while ((c = cin.get()) != EOF)	// 等效 while (cin.get(c)){
{
    // 如果不判断,换行符也会打印
    if (c != '\n') {
        cout << c << endl;
    }
}


// Demo2: 读取字符串
char arr[5];
cin.get(arr, 5, '\n');	// 最多四个字符,最后一个存'\0'

标准库STL

也就是使用using namespace std;

IO库:

  • iostream:标准输入输出流cin、cout、clog、cerr
  • fstream:文件输入输出流ifstream、ofstream、fstream
  • sstream:字符串流istringstream、ostringstream、stringstream
  • cstdio: 与C 风格的输入输出函数printf、scanf
  • cstdlib:与C 标准库相关的实用函数exit、system、atoi
    • 内存管理malloc(size_t sizie)、free(void* ptr)
    • 程序控制exit(int status)、system(const char* command)、abort()
    • 数学:rand()、srand(unsigned int seed)、abs(int n)、div(numer, denom);
    • 转换函数:atoi(const char* str)、atof(const char* str) 、strtol(const char* str, char** endptr, int base)

容器库:

  • vector:动态数组,允许按索引访问元素。
  • list:双向链表,高效增删
  • deque:双端队列,两端增删
  • set:集合,自动排序不重复。
  • map:映射,键值对存储。自动排序
  • unordered_set:同上,没有顺序,查找更高效
  • unordered_map:同上,没有顺序,查找更高效
  • stack:栈,后进先出(LIFO)
  • queue:队列,先进先出(FIFO)
  • priority_queue:按优先级访问队列元素

算法库:

  • algorithm:提供常用算法,比如sort、find、reverse、
  • functional:提供函数对象、函数指针等功能std::bind、std::function、std::mem_fn 等。
  • numeric:提供数值算法,如累加、乘积、最大最小值等(例如 accumulate、inner_product)。

字符串库:

  • string: C++ 字符串类 std::string,支持动态字符串操作。
  • cstring:C 风格的字符串操作,类似于 C 语言中的 <string.h>,提供如 strlen、strcpy、strcmp 等函数。

数学库:

  • cmath:提供数学函数,如三角函数、指数函数、对数函数等(例如 sin、cos、log、sqrt)。
  • cstdlib:说过rand()
  • complex:复数
  • valarray:支持数学运算数组,高效

时间:

  • ctime:C 风格的时间函数,支持获取当前时间、格式化输出等功能
  • chrono:可以进行精确的时间测量、延时等操作。

线程和并发库:

  • thread:创建和管理线程
  • mutex:提供互斥锁,用于线程同步
  • atomic:提供原子操作,支持无锁编程
  • condition_variable:提供条件变量,用于线程间的协调

类型支持库:

  • type_traits:提供类型相关的工具,如检查类型、判断类型特性、类型转换等。
  • memory:提供智能指针(如 std::unique_ptr、std::shared_ptr)和内存管理功能。
  • utility:提供实用的工具函数,如 std::swap、std::move、std::pair 等。

异常处理库:

  • exception:提供 C++ 异常处理的基础类,如 std::exception。
  • stdexcept:提供标准的异常类,如 std::out_of_range、std::invalid_argument 等。

输入输出(文件系统):

  • filesystem:提供文件和目录操作的支持(如创建、删除、重命名文件、遍历目录等)。

其他库:

  • initializer_list:初始化列表的支持,允许在构造时使用花括号初始化对象。
  • bitset:提供位集操作
  • random:提供随机数
  • locale:提供区域设置和文化特性相关的功能

其他

long的数据类型长度:

已知:操作系统字长和机器字长未必一致(比如某些操作系统可能在 64 位的机器上运行),编译器根据操作系统字长来定义int字长。

在32位操作系统中,long为32位。在64位操作系统中,long在Linux上为64位,在Windows中则为32位,这是因为 Windows 的 64 位 ABI(应用程序二进制接口)并未改变 long 类型的大小。

VS code

配置C++步骤

  • 安装好 gcc、g++ 和 gdb 等工具。
  • VS Code 中安装 C/C++ 扩展
  • 资源管理器中创建一个文件夹,并用vs code打开。
  • 然后就可以新建文件demo.cpp然后选择编译器直接运行或调试。

查看C++对应汇编:

// 在调试控制台输入

-exec disassemble /m

问题

inline

友元函数的AB类访问问题


http://www.kler.cn/a/513493.html

相关文章:

  • 在k8s中部署一个可外部访问的Redis Sentinel
  • 金融场景 PB 级大规模日志平台:中信银行信用卡中心从 Elasticsearch 到 Apache Doris 的先进实践
  • iOS UIScrollView的一个特性
  • python milvus及curl命令进行query请求
  • 【Linux】Linux入门(三)权限
  • 2024年度总结:从后端Java到全栈成长的蜕变
  • 除了基本的事件绑定,鸿蒙的ArkUI
  • H3CNE-18-Telnet远程控制
  • [分治] FBI树
  • Python爬虫技术:高效数据收集与深度挖掘
  • 算法项目实时推流
  • Redis:解锁集群共享Session的秘密武器
  • 二、vue智能Ai对话(高仿通义千问)流式进阶版
  • 深入解析HDFS:定义、架构、原理、应用场景及常用命令
  • HDFS HADOOP分布式文件系统
  • 快速掌握异常(含面试题)
  • Linux 更换yum镜像源
  • 小米平板pad6工程固件界面预览 修复tee损坏 修复底层分区 开diag端口
  • Apache Tomcat文件包含漏洞复现(详细教程)
  • C语言小任务——1000以内含有9的数字
  • 第3章 存储系统
  • 偏序关系.
  • LeetCode hot 力扣热题100 翻转二叉树
  • 最新百应abogus纯算还原流程分析
  • WPF2-1在xaml为对象的属性赋值.md
  • DOL-288 多功能电子计时器说明书