怎么做一网站,商业网点的定义,wordpress跳转后端IP,品牌管理公司网站建设C基础语法
C和c的区别 c中new和delete是对内存分配的运算符#xff0c;取代了c中的malloc和free 标准c中的字符串类取代了标准c函数库头文件中的字符数组处理函数(c中没有字符串类型). 在c中#xff0c;允许有相同的函数名#xff0c;不过他们的参数类型不能完全相同基础语法
C和c的区别 c中new和delete是对内存分配的运算符取代了c中的malloc和free 标准c中的字符串类取代了标准c函数库头文件中的字符数组处理函数(c中没有字符串类型). 在c中允许有相同的函数名不过他们的参数类型不能完全相同这样这些函数就可以相互区分开来。而在c语言中是不允许的。也就是c可以重载c不允许. c用来做控制态输入输出的iostream类库代替了c中的stdio。 c语言中允许变量定义语句在程序中的任何地方只要在是使用它之前就可以而c语言中必须要在函数开头部分的。c不允许重复定义变量c语言也是做不到的。 c中除了值和指针之外还加了引用。引用变量是其它变量的一个别名我们可以认为他们只是名字不相同其它都是相同的
1.c为什么支持函数重载c语言不支持函数重载 C代码产生函数符号的时候函数名参数列表类型组成的! C代码产生函数符号的时候函数名来决定! I
重载和重写的区别 重载 重载是指在同一范围内定义中的同名成员函数才存在重载关系。主要特点就是函数名相同参数类型和数目有所不同不能出现参数个数和类型均相等的情况仅仅依靠返回值不同来区分的函数。重载和函数成员是否是虚函数无关。 重写 重写指的是派生类中覆盖基类中的同名函数重写就是重写函数体要求基类函数必须是虚函数且 与基类的虚函数有相同的参数个数 与基类的虚函数有相同的参数类型 与基类的虚函数有相同的返回值类型 举例子 //父类class A{public:virtual int fun(int a){}}//子类classB : class A{public://重写一般加override可以确保是重写父类的函数virtual int fun(int a)override{}}
重载与重写的区别: 重写是父类和子类之间的垂直关系重载是不同函数之间的水平 重写要求参数列表相同重载则要求参数列表不同返回值不要求 重写关系中调用方法根据对象类型决定重载根据调用时实参表与形参表的对应关系来选择函数体
讲一下c的三中继承 public继承 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时都保持原有的状态而基类的私有成员任然是私有的不能被这个派生类的子类所访问。 protected继承 保护继承的特点是基类的所有公有成员和保护成员都称为派生类的保护成员并且只能被它的派生类成员函数或友元函数所访问基类的私有成员仍然是私有的 private继承 私有继承的特点是基类的所有公有成员和保护成员都为派生类的私有成员并不被他的派生子类所访问基类的成员只能由派生类访问无法继续往下访问
指针和引用的区别 指针是一个变量存储的是一个地址引用跟原来的变量实质上是同一个东西是变量的别名。 指针有多级而引用只有一级 指针可以为空但是引用不能为空且定义时必须初始化 指针在初始化后还可以改变指向但是引用不可以 sizeof指针得到的是指针的大小引用得到是所指向的大小
结构体对齐讲一讲 int double int的大小
抽象类和普通类有什么区别 //动物的基类 泛指 类-》抽象一个实体的类型//定义Animal 的初衷 并不是让Anmail抽象某个实体的类型//作用://1. string _name 让所有动物实体类通过继承Animal直接复用该属性//2. 给所有的派生类保留同一的覆盖/重写接口//拥有纯虚函数的类 就是抽象类// 抽象类不能实例化对象但是可以定义指针和引用的变量class Animal{public:Animal(string) : _name(name){}virtual void bark() 0;//纯函数protected:string _name;};class Cat : public Animal{public:Cat(string name) :Animal(name){}void bark() { cout_namebark :miao miaoendl;}};class Dog : public Animal{public:Dog (string name) :Animal(name){}void bark() { cout_namebark :wang wangendl;};//这个如果每个都加下面的话就太麻烦了 如果新新添加或者删除的话就不好了/*void bark(Cat cat){cat.bark();}void bark(Dog dog){dog.bark();}*/void bark(Animal *p){p - bark();//Anmail :: bark 虚函数动态绑定le//p-cat cat vftable Cat::bark}//这个就是多态int main(){Cat cat(秘密)Dog dog(jj);bark(cat);bark(dog);} 一般把什么设置成抽象类
对多态的理解 定义同一事物表现出不同事务的能力即向不同对象发送同一信息不同的对象在接受时会产生不同的行为(重载实现编译时多态虚函数实现运行时多态) 功能多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术赋值之后父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作; 简单一句话允许将子类类型的指针赋值给父类类型的指针。
实现多态有两种方式 1.覆盖(override)是指子类重新定义父类的虚函数的做法
2.重载(overload)是指允许存在多个同名函数而这些函数的参数表不同或许参数个数不同或许参数类型不同或许两者都不同
例如
基类是一个抽象———人那学生、运动员也是人而使用这个抽象对象既可以表示学生、也可以表示运动员。 class Animal{public:Animal(string) : _name(name){}virtual void bark() {}//这个是叫的虚函数protected:string _name;};class Cat : public Animal{public:Cat(string name) :Animal(name){}void bark() { cout_namebark :miao miaoendl;}};class Dog : public Animal{public:Dog (string name) :Animal(name){}void bark() { cout_namebark :wang wangendl;};//这个如果每个都加下面的话就太麻烦了 如果新新添加或者删除的话就不好了/*void bark(Cat cat){cat.bark();}void bark(Dog dog){dog.bark();}*/void bark(Animal *p){p - bark();//Anmail :: bark 虚函数动态绑定le//p-cat cat vftable Cat::bark}//这个就是多态int main(){Cat cat(秘密)Dog dog(jj);bark(cat);bark(dog);} std::function 可以容纳不同签名的可调用对象实现多态性。#include iostream#include functionalvoid printMessage(const std::string message) {std::cout message std::endl;}void printNumber(int number) {std::cout Number: number std::endl;}int main() {// 使用 std::function 容纳不同签名的函数std::functionvoid(const std::string) func1 printMessage;std::functionvoid(int) func2 printNumber;// 调用包装的函数func1(Hello, world!); // 输出Hello, world!func2(42); // 输出Number: 42return 0;} 继承在讲一讲
定义
让某种类型对象获得另一个类型对象的属性和方法。
功能
它可以使用现有类的所有所能并在无需重新编写原来的类的情况下对这些功能进行扩展
常见的继承有三种方式
1、实现继承指使用基类的属性和方法而无需额外编码的能力。
2、接口继承指仅使用属性和方法的名额、但是子类必须提供实现的能力
3、可视继承指子窗体类使用基窗体类的外观和实现代码的能力
例如
将人定义为一个抽象类拥有姓名、性别、年龄等公共属性吃饭、睡觉等公共方法在定义一个具体的人时就可以继承这个抽象类既保留了公共属性和方法也可以在此基础上扩展跳舞、唱歌等特有方法。 class A{public:int ma;protive:int mb;private:int mc;}class B : public A{public:int md;protive:int me;private:int mf;} 派生类从继承可以继承来所有的成员(变量和方法)除过构造函数和析构函数I 派生类怎么初始化从基类继承来的成员变量呢?解答: 通过调用基类相应的构造函数来初始化 派生类的构造函数和析构函数负责初始化和清理派生类部分派生类从基类继承来的成员的初始化和清理由谁负责呢? 是由基类的构造和析构函数来负责 派生类对象构造和析构的过程是: 1.派生类调用基类的构造函数初始化从基类继承来的成员. 2.调用派生类自己的构造函数初始化派生类自己特有的成员.派生类对象的作用域到期了 3.调用派生类的析构函数释放派生类成员可能占用的外部资源(堆内存文件) 4.调用基类的析构函数释放派生类内存中于从基类继承来的成员可能占用的外部资源(堆内存文件)
虚函数调用过程 调用过程 当调用虚函数时编译器会生成一个虚函数表其中包含了类的虚函数地址。每个对象都包含一个指向虚函数表的指针(通常是在对象的内存布局中的一个隐藏字段)。当您通过基类指针或引用调用虚函数时实际上是根据该对象的虚函数表来调用适当的函数。这确保了正确的函数版本被调用。
总的来说虚函数的调用过程包括定义虚函数创建派生类创建对象然后通过基类指针或引用来调用虚函数。在运行时根据对象的实际类型确定调用的函数版本这样可以实现多态性。这使得c能够在运行时动态选择正确的函数而不是在编译时静态确定。 定义一个Base 类型的指针 如果 Base中show不是虚函数 就直接调用 静态绑定 pb Base* 如果是虚函数 *pb 指向的就是Derive派生类对象变成动态绑定
虚函数讲一讲
虚函数是指一个类中你希望重载的成员函数。当你用一个基类指针或引用指向一个继承类对象的时候调用一个虚函数时实际调用的是继承类的版本。虚函数的主要目的实现多态这是面向对象编程的一个重要特性。
例如 #include iostreamclass Animal {public:virtual void makeSound() {std::cout The animal makes a sound std::endl;}};class Dog : public Animal {public:void makeSound() override {std::cout The dog barks std::endl;}};int main() {Animal* animal new Dog();animal-makeSound(); // 输出 The dog barksdelete animal;return 0;}
在这个例子中Animal 类有一个虚函数 makeSound()Dog 类继承了 Animal 类并重写了 makeSound() 函数。当我们通过基类指针调用 makeSound() 时实际上调用的是派生类 Dog 的实现。这就是虚函数实现多态的一个例子
new和delete的原理
实现过程 new的实现过程是调用名为operator new的标准库函数分配足够大的原始类为类型化的内存以保寸指定类型的一个对象接下来运行该类型的一个构造函数用指定初始化构造函数最后返回指向新分配并构造后的对象指针 new 用于在堆heap上分配内存空间以存储一个或多个对象。new 会调用适当的构造函数来初始化对象。new 返回指向分配内存的指针允许您在程序的其他地方访问该对象。如果分配失败例如没有足够的内存可用new 可能引发 std::bad_alloc 异常您可以使用 try-catch 块来捕获它。 delete的实现过程对指针指向的对象运行适当的析构函数然后通过调用名为operator delete的标准库函数释放该对象所用的内存。 delete 用于释放先前由 new 分配的内存。delete 会调用适当的析构函数来销毁对象。delete 接受指向要释放内存的指针并将该内存返回给系统堆池以便将其重复利用。如果使用 delete 后未将指针设置为 nullptr或 NULL则可能会导致悬空指针dangling pointer问题。
new和malloc
1、 new/delete是C关键字需要编译器支持。malloc/free是库函数需要头文件支持
2、 使用new操作符申请内存分配时无须指定内存块的大小编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
3、 new操作符内存分配成功时返回的是对象类型的指针类型严格与对象匹配无须进行类型转换故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * 需要通过强制类型转换将void*指针转换成我们需要的类型。
4、 new内存分配失败时会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
5、 new会先调用operator new函数申请足够的内存通常底层使用malloc实现。然后调用类型的构造函数初始化成员变量最后返回自定义类型指针。delete先调用析构函数然后调用operator delete函数释放内存通常底层使用free实现。malloc/free是库函数只能动态的申请和释放内存无法强制要求其做自定义类型对象构造和析构工作。
C中有几种类型的new
在C中new有三种典型的使用方法plain newnothrow new和placement new vector中push_back和emplace_back的区别
内联函数内联函数的缺点
仿函数
关键字
const 关键字
const的作⽤
被它修饰的值不能改变是只读变量。必须在定义的时候就给它赋初值。
1、常量指针底层const
常量指针
是指定义了⼀个指针这个指针指向⼀个只读的对象不能通过常量指针来改变这个对象的值。常量指针强调的是
指针对其所指对象的不可改变性。
特点
靠近变量名。
形式
1const 数据类型 *指针变量 变量名
2数据类型 const *指针变量 变量名
⽰例 int temp 10;const int* a temp;int const *a temp;// 更改*a 9; // 错误只读对象temp 9; // 正确
2、指针常量顶层const
指针常量
指针常量是指定义了⼀个指针这个指针的值只能在定义时初始化其他地⽅不能改变。指针常量强调的是指针的
不可改变性。
特点
靠近变量类型。
形式
数据类型 * const 指针变量变量名 int temp 10;int temp1 12;int* const p temp;// 更改p temp2; // 错误*p 9; // 正确 define 和 typedef 的区别
define 只是简单的字符串替换没有类型检查 是在编译的预处理阶段起作⽤ 可以⽤来防⽌头⽂件重复引⽤ 不分配内存给出的是⽴即数有多少次使⽤就进⾏多少次替换
typedef 有对应的数据类型是要进⾏判断的 是在编译、运⾏的时候起作⽤ 在静态存储区中分配空间在程序运⾏过程中内存中只有⼀个拷贝
define 和 inline 的区别
1、define
定义预编译时处理的宏只是简单的字符串替换⽆类型检查不安全。
2、inline
int temp 10;
int temp1 12;
int* const p temp;
// 更改
p temp2; // 错误
*p 9; // 正确inline是先将内联函数编译完成⽣成了函数体直接插⼊被调⽤的地⽅减少了压栈跳转和返回的操作。没有普
通
函数调⽤时的额外开销
内联函数是⼀种特殊的函数会进⾏类型检查
对编译器的⼀种请求编译器有可能拒绝这种请求
C中inline编译限制 不能存在任何形式的循环语句 不能存在过多的条件判断语句 函数体不能过于庞⼤ 内联函数声明必须在调⽤语句之前
override 和 overload
1、override是重写覆盖了⼀个⽅法
以实现不同的功能⼀般是⽤于⼦类在继承⽗类时重写⽗类⽅法。
规则 重写⽅法的参数列表返回值所抛出的异常与被重写⽅法⼀致 被重写的⽅法不能为private 静态⽅法不能被重写为⾮静态的⽅法 重写⽅法的访问修饰符⼀定要⼤于被重写⽅法的访问修饰符publicprotecteddefaultprivate
2、overload是重载这些⽅法的名称相同⽽参数形式不同
⼀个⽅法有不同的版本存在于⼀个类中。
规则 不能通过访问权限、返回类型、抛出的异常进⾏重载 不同的参数类型可以是不同的参数类型不同的参数个数不同的参数顺序参数类型必须不⼀样 ⽅法的异常类型和数⽬不会对重载造成影响
使⽤多态是为了避免在⽗类⾥⼤量重载引起代码臃肿且难于维护。
重写与重载的本质区别是,加⼊了override的修饰符的⽅法,此⽅法始终只有⼀个被你使⽤的⽅法。
new 和 malloc
1、new内存分配失败时会抛出bac_alloc异常它不会返回NULLmalloc分配内存失败时返回NULL。
2、使⽤new操作符申请内存分配时⽆须指定内存块的⼤⼩⽽malloc则需要显式地指出所需内存的尺⼨。
3、opeartor new /operator delete可以被重载⽽malloc/free并不允许重载。
4、new/delete会调⽤对象的构造函数/析构函数以完成对象的构造/析构。⽽malloc则不会
5、malloc与free是C/C语⾔的标准库函数,new/delete是C的运算符
6、new操作符从⾃由存储区上为对象动态分配内存空间⽽malloc函数从堆上动态分配内存。
constexpr 和 const
const 表⽰“只读”的语义constexpr 表⽰“常量”的语义
constexpr 只能定义编译期常量⽽ const 可以定义编译期常量也可以定义运⾏期常量。
你将⼀个成员函数标记为constexpr则顺带也将它标记为了const。如果你将⼀个变量标记为constexpr则同样它
是const的。但相反并不成⽴⼀个const的变量或函数并不是constexpr的。
static
作⽤实现多个对象之间的数据共享 隐藏并且使⽤静态成员还不会破坏隐藏原则默认初始化为0
前置与后置 self operator() {node (linktype)((node).next);return *this;}const self operator(int) {self tmp *this;*this;return tmp;}
为了区分前后置重载函数是以参数类型来区分在调⽤的时候编译器默默给int指定为⼀个0
1、为什么后置返回对象⽽不是引⽤
因为后置为了返回旧值创建了⼀个临时对象在函数结束的时候这个对象就会被销毁如果返回引⽤那么我请问
你你的对象对象都被销毁了你引⽤啥呢
2、为什么后置前⾯也要加const
其实也可以不加但是为了防⽌你使⽤i,连续两次的调⽤后置重载符为什么呢?
原因
它与内置类型⾏为不⼀致你⽆法活得你所期望的结果因为第⼀次返回的是旧值⽽不是原对象你调⽤两次后
置结果只累加了⼀次所以我们必须⼿动禁⽌其合法化就要在前⾯加上const。
3、处理⽤户的⾃定义类型
最好使⽤前置因为他不会创建临时对象进⽽不会带来构造和析构⽽造成的格外开销。
c和c中const的区别是什么 const的编译方式不同c中const就是当作一个变量来编译生成指令的. c中所有出现const常量名字的地方都被常量的初始化替换了! !! bind的用法
我们通常是在 C 中进行函数绑定的上下文中。std::bind 是一个非常有用的函数模板它允许你创建一个可调用对象函数、函数指针、成员函数等并绑定一些参数或者改变调用时的顺序。这对于在一些场景中很方便特别是在涉及回调、函数对象、线程等情况下。
以下是一个简单的例子来说明 std::bind 绑定全局函数的基本用法 #includiostream#includefunction//一个简单的函数void greet(consr std::string name,const std::string greeting){std::contgreeting, name!std::endl;}int main(){//使用bind绑定器绑定greet函数的第一个参数auto greetSomeone std::bind(greet, std::placeholders::_1,hello)//调用可以调用的对象greetSomeone(Alice);//输出 helloAlice!greetSomeone(Bob);//输出hello,Bob!}
在这个例子中std::bind 用于创建一个可调用对象 greetSomeone它是 greet 函数的一个变体其中第一个参数name被绑定为 std::placeholders::_1而第二个参数greeting被指定为常量字符串 Hello。
bind绑定非静态成员函数 #include functional#include iostreamclass MyClass {public:void printMessage(const std::string message) {std::cout Message: message std::endl;}};int main() {MyClass obj;// 使用 std::bind 绑定非静态成员函数auto func std::bind(MyClass::printMessage, obj, std::placeholders::_1);// 调用包装的成员函数func(Hello, world!); // 输出Message: Hello, world!return 0;}
在这个例子中使用 std::bind 绑定了 MyClass 中的非静态成员函数 printMessage。需要注意的是obj 作为额外的参数传递给 std::bind代表了 this 指针。
绑定成员函数和对象
如果你希望在绑定时不显式传递对象而是在调用时传递可以使用 std::placeholders::_1 占位符占位。 #include functional#include iostreamclass MyClass {public:void printMessage(const std::string message) {std::cout Message: message std::endl;}};int main() {MyClass obj;// 使用 std::bind 绑定成员函数和对象auto func std::bind(MyClass::printMessage, std::placeholders::_1);// 调用包装的成员函数传递对象作为参数func(obj, Hello, world!); // 输出Message: Hello, world!return 0;}
在这个例子中std::placeholders::_1 占位符占位了对象参数而在调用时通过 func(obj, Hello, world!) 传递了实际的对象。
一些关键概念 std::placeholders::_1这是一个占位符表示绑定时应该被替代的第一个参数。在这里它代表 greetSomeone 被调用时传递的参数。 greetSomeone 是一个可调用对象它被绑定到 greet 函数并预设了一个参数Hello所以当你调用 greetSomeone(Alice) 时实际上就是调用了 greet(Alice, Hello)。
function的用法
std::function 提供了一种通用的、类型安全的方式来包装和存储可调用对象。以下是 std::function 的一些详细用法
基本用法 #include iostream#include functionalint add(int a, int b) {return a b;}int main() {// 使用 std::function 包装函数std::functionint(int, int) func add;// 调用包装的函数int result func(3, 4);std::cout Result: result std::endl; // 输出Result: 7return 0;}
Lambda 表达式 #include iostream#include functionalint main() {// 使用 std::function 包装 Lambda 表达式std::functionint(int, int) func [](int a, int b) {return a * b;};// 调用包装的 Lambda 表达式int result func(3, 4);std::cout Result: result std::endl; // 输出Result: 12return 0;}
函数对象 #include iostream#include functional// 函数对象struct Multiply {int operator()(int a, int b) const {return a * b;}};int main() {// 使用 std::function 包装函数对象std::functionint(int, int) func Multiply();// 调用包装的函数对象int result func(3, 4);std::cout Result: result std::endl; // 输出Result: 12return 0;}
多态性 #include iostream#include functionalvoid printMessage(const std::string message) {std::cout message std::endl;}void printNumber(int number) {std::cout Number: number std::endl;}int main() {// 使用 std::function 容纳不同签名的函数std::functionvoid(const std::string) func1 printMessage;std::functionvoid(int) func2 printNumber;// 调用包装的函数func1(Hello, world!); // 输出Hello, world!func2(42); // 输出Number: 42return 0;}
绑定参数 #include iostream#include functionalint add(int a, int b) {return a b;}int main() {// 使用 std::bind 绑定参数std::functionint(int) add5 std::bind(add, std::placeholders::_1, 5);// 调用包装的函数int result add5(10);std::cout Result: result std::endl; // 输出Result: 15return 0;}
这些示例涵盖了 std::function 的基本用法包括包装函数、Lambda 表达式、函数对象、多态性、绑定参数以及清空或重置等方面。希望这能够帮助你更好地理解和使用 std::function。
Protocol Buffersprotobuf是一种由Google开发的轻量级的数据交换格式它可以用于结构化数据的序列化类似于 XML 或 JSON但更轻量、更高效。Protocol Buffers 不仅用于数据的序列化和反序列化还可以定义数据结构和接口。
以下是 Protocol Buffers 序列化的基本原理和用法
Protocol Buffers 的定义
Protocol Buffers 使用 .proto 文件来定义数据结构和消息格式。一个简单的 .proto 文件如下 protoCopy codesyntax proto3;message Person {required string name 1;required int32 id 2;optional string email 3;}
在这个例子中我们定义了一个名为 Person 的消息其中包含了 name、id 和 email 三个字段。每个字段都有一个唯一的标识号用于在二进制序列中标识字段。
使用 Protocol Buffers 编译器
将 .proto 文件编译成对应的编程语言的类文件可以使用 Protocol Buffers 编译器。例如使用 protoc 编译器可以将上述 .proto 文件编译成 C 代码 bashCopy codeprotoc --cpp_out. your_proto_file.proto
序列化和反序列化
在编程语言中你可以使用生成的 Protocol Buffers 类来序列化和反序列化数据。以下是一个简单的 C 示例 cppCopy code#include your_proto_file.pb.h#include iostream#include fstreamint main() {// 创建一个 Person 对象Person person;person.set_name(John Doe);person.set_id(123);person.set_email(john.doeexample.com);// 序列化std::string serializedData;person.SerializeToString(serializedData);// 反序列化Person deserializedPerson;deserializedPerson.ParseFromString(serializedData);// 输出反序列化后的数据std::cout Name: deserializedPerson.name() std::endl;std::cout ID: deserializedPerson.id() std::endl;std::cout Email: deserializedPerson.email() std::endl;return 0;}
在这个例子中我们使用 SerializeToString 将 Person 对象序列化为字符串然后使用 ParseFromString 将字符串反序列化为另一个 Person 对象。序列化后的数据可以存储在文件中、通过网络传输等方式。
4. Protocol Buffers 的优势 高效性 Protocol Buffers 使用二进制格式相比 XML 和 JSON 更加紧凑占用更少的空间。 速度快 序列化和反序列化的速度比 XML 和 JSON 更快。 可扩展 可以在不破坏现有数据的情况下轻松添加或删除字段使其具有很好的向前和向后兼容性。
总体而言Protocol Buffers 是一种强大且高效的数据序列化工具特别适用于需要高性能和小数据大小的场景如分布式系统通信、数据存储和通信协议定义。
序列化
序列化是将数据结构或对象转换为字节流二进制数据或其他格式的过程以便将其存储在文件中、通过网络发送或在不同系统之间传输。序列化后的数据通常可以被反序列化还原为原始的数据结构或对象。
为什么需要序列化 数据持久化 将数据保存在文件中以便在程序关闭后重新加载。 数据传输 在网络上传输数据例如客户端和服务器之间的通信。 进程间通信 在不同的进程之间共享数据。
json序列化
JSONJavaScript Object Notation是一种轻量级的数据交换格式广泛用于前后端之间的数据传输。JSON 序列化即将数据结构或对象转换为 JSON 格式的字符串而 JSON 反序列化则是将 JSON 格式的字符串还原为原始的数据结构或对象。
Lambda表达式
Lambda 表达式是 C11 引入的一项特性它允许在代码中以一种更为简洁和方便的方式定义匿名函数。Lambda 表达式的本质可以从以下几个方面来理解 匿名函数 Lambda 表达式实际上是一个匿名函数即没有显式名称的函数。它允许你在需要函数的地方直接定义函数而不必显式地写出函数名。 语法糖 Lambda 表达式是 C 对函数对象function object的一种语法糖使得使用函数对象更为简洁。在使用 Lambda 表达式之前我们通常需要使用函数对象或函数指针来传递函数Lambda 表达式使这一过程变得更加直观。 闭包 Lambda 表达式可以捕获其定义位置的变量形成一个闭包closure。通过捕获变量Lambda 表达式可以在其生命周期内访问这些变量即使这些变量在定义 Lambda 表达式的作用域之外。 #icnludeiostreamint main(){//lambda表达式没有捕获变量auto add [](int a,int b){return a b;};//使用lamabda表达式int result add(2,3);cuotresult:resultendl;return 0;} 在这个例子中auto add [](int a, int b) { return a b; }; 定义了一个 Lambda 表达式它接受两个整数参数并返回它们的和。Lambda 表达式使用 auto 关键字因为编译器能够推断出 Lambda 表达式的类型。 Lambda 表达式的本质是一种语法糖它提供了更简洁的语法来定义函数并允许在函数内部捕获外部变量使得代码更为灵活和直观。