push_back 和 emplace_back 的区别

news2024/12/31 1:32:07

文章目录

  • 1、vector::push_back
    • 1.1 void push_back(T&& x) ; (C++11)
      • 参数
      • 返回值类型
      • 大小 和 容量
      • 移动左值
      • 用户自定义类型使用 push_back
    • 1.2 void push_back(const T &x);
      • 参数
      • 返回值类型
    • 1.3 如果 vector 的 size 超过当前capacity,push_back 会使迭代器、指针和引用失效
  • 2、vector::emplace_back
    • 参数
    • 返回值类型
    • 自定义类型
    • 如果发生重新分配,则迭代器、指针和引用无效
  • 3、push_back VS emplace_back
    • 区别1:如果构造函数接受多个参数,push_back 只接受该类型的唯一对象,而 emplace_back 则接受该类型构造函数的参数。
    • 区别2:效率
      • built-in type
      • User-defined type
  • 4、参考

1、vector::push_back

push_back 函数的作用是在 vector 容器的末尾添加数据,

函数原型:(两个版本)

void push_back(T&& x) ; (C++11)
void push_back(const T& x);

push_back 允许在没有内存预留的情况下,也能轻松地将数据附加进 vector 中。

在数组中,存储的大小是固定的,如果需要扩大数组大小,必须分配另一个更大的数组,并将内容复制到新数组。这无疑需要额外的代码,而且如果这个过程重复发生,将内容复制到新数组将消耗大量时间,从而极大地减慢程序速度。

为避免使用固定大小的数组时可能发生的所有不可避免的问题,可以将其替换为vector,并在想要向 vector 添加额外数据时调用push_back 函数。因为 vector 可以进行内存调整,所以无论它可能有多大,你都可以放心。

下面给出了一个代码示例。

int arr[3] = {2, 34, 900};

vector<int> vec = {23};
vec.push_back( 34 ); //second element added
vec.push_back( 100 ); //third element added
vecc.push_back( 500 ); //fourth element added
/* ..you can keep adding data **/
for(auto elem:vec ) //accessing vector element using range-based for loop
{
	cout << elem << ” ”;
}

输出:23 34 100 500

可见,vector 可以接收尽可能多的数据,而不用担心存储空间不足(假设有足够的内存)。vector 实际上是数组的完美替代品。

1.1 void push_back(T&& x) ; (C++11)

参数

x —— 添加到 vector 末尾的是右值

返回值类型

void

当要添加的数据是 右值 时,该函数会被调用。由于它接受右值,因此它会移动数据而不是复制数据。

vector<int> vec;

vec.push_back(23); //calls this version

cout << vec[0]; //23 

大小 和 容量

如果此前没有预留存储空间,该函数会扩大容量。但是,如果使用 reserve() 函数预留了存储空间,这个函数就只会增加其大小而不是容量。当你添加的数据超过预留的大小时,容量才会增加。

vector<string> vecSt={“Angry”}, vecSt1;
 
cout << “vecSt capacity before calling push_back =<< vecSt.capacity();
 
vecSt.push_back(“Sad”); //calls this version
 
cout << “vecSt capacity after calling push_back =<< vecSt.capacity( ) ;
 
vecSt1.reserve(3); //Size reserve for three elements
 
vecSt1.push_back( “Jealousy” );
vecSt1.push_back( “Hatred” );
vecSt1.push_back( “Crime” );
 
cout << “vecSt1 capacity after calling push_back =<< vecSt1.capacity( ) ;
 
vecSt1.push_back(“Law”) ;
 
cout << “vecSt1 capacity after adding 4th data =<< vecSt1.capacity( ) ;

输出:

vecSt capacity before calling push_back = 1
vecSt capacity after calling push_back = 3
vecSt1 capacity after calling push_back = 3
vecSt1 capacity after adding 4th data = 6

增加多少容量取决于编译器,在上述例子中,容量在第一次 push_back 调用时增加 2,并在随后的每次 push_back 调用中增加 1。

移动左值

如果你传递的参数是个左值,那么第二个版本的 push_back 会被调用。但是如果你想调用这个版本来移动一个左值到 vector 中,请使用函数 std::move()

vector<int> vec;

int val = 90;

vec.push_back(val) ; ///calls the second version

vec.push_back(std::move(val)); ///calls this version

用户自定义类型使用 push_back

当类型是用户自定义类型:类 或者 结构体。

如果自定义类型的构造函数只有一个参数,可以用 push_back 添加一个该类型的对象或者直接传递构造函数接收的参数类型一样的数据。

class Data {
	int i;
 
public:
	Data(int ii):i(ii) {} 
	~Data ( ) { }
};

vector<Data> vec;

vec.push_back(Data(78)) ;//adding an object of Data

vec.push_back(89); //work fine,Data constructor accept integer 

传递原始数据是可以接受的,因为 push_back 函数将创建该类型的临时对象,该临时对象将再次复制到 vector 中。

如果 vector 类型的构造函数接收的参数超过1个,那就只能用 push_back 添加该类型的对象,而不能直接串原始数据。push_back 不能接收两个参数

class Type
{
	int i;
	string s ;
 
public:
	Type(int ii ,string ss): i(ii), s(ss) { }
	 
	~Type( ) { }
};
 
vector<Type> vec;
 
vec.push_back(Type(78, “Hello”)); //adding an object of Type
 
vec.push_back(89,”World”); //Error!,raw data is passed

1.2 void push_back(const T &x);

参数

x —— 添加到vector 末尾的值

返回值类型

void

如果传递的参数是 左值 或者 引用 时,该版本就会被调用。在调用此函数时,如果 vector 预留了一些存储空间,则容量保持不变,但如果没有,则容量将随着其大小而增加。

vector<int> vec={23}, vec1;
int val = 90 , &ref = val;
 
vec1.reserve(2);
 
cout << “vec capacity before push_back call =<< vec.capacity( ) << endl;
 
vec.push_back(ref);
 
cout << “vec capacity after push_back call =<< vec.capacity( ) << endl;
 
cout << “vec capacity before push_back call =<< vec1.capacity( ) << endl;
 
vec1.push_back(ref);
 
cout << “vec capacity after push_back call =<< vec1.capacity( ) << endl; 

输出:

vec capacity before push_back call = 1
vec capacity after push_back call = 3
vec1 capacity before push_back call = 2
vec1 capacity after push_back call = 2

1.3 如果 vector 的 size 超过当前capacity,push_back 会使迭代器、指针和引用失效

假设没有为 vector 预留存储空间,并且假设另一个迭代器指向该向量。在这种情况下,调用 push_back 函数将增加大小及其容量,这也会使迭代器无效。请看下面给出的代码示例。

vector<char> vecC={‘B’,‘M’};
 
vector<char>::iterator vecCIt=vecC.begin( );
 
cout << vecCIt[0] << ” ” << vecCIt[1] << endl;
 
vec.push_back(‘L’);
 
cout << vecCIt[0];//undefined,vecCIt is invalidated

输出:

B M
undefined value

不过,如果你已经预留了一些存储空间,那么只要添加的元素小于或等于预留大小,迭代器就是有效的。一旦添加的数据超过当前预留容量,迭代器就会失效。

vector<int> vec;
 
vec.reserve(2);
 
vector<int>::iterator vecIt=vec.begin( );
 
vec.push_back(90);
 
cout << vecIt[0] << vec[1] << endl; ///work fine
 
ve.push_back(45);
 
cout << vecIt[0] << ” ” vecIt[1] << endl; ///work fine
 
vec.push_back(505); //adds the 3rd data
 
cout << vecIt[0] endl ; //undefined
cout << vecIt[1] ;//undefined

输出:

90
90 45
undefined value
undefined value

当添加的数据超过预留大小时,就会进行新的分配。重新分配后,存储空间将有新的地址,但迭代器仍指向之前的存储空间,而现在存储空间已失效,因此迭代器失效。

2、vector::emplace_back

功能和 push_back 一样,都是往 vector 的末尾添加数据,它是在C++11版本中新增的。该函数的声明如下:

template<typename… Args> void emplace_back(Args&&… args);

参数

args—— 单个参数或参数列表

返回值类型

viod

使用示例:

vector<int> vec ={23, 56, 89};
 
vec.emplace_back(981);
vec.push_back(1425);
 
for( auto elem:vec )
{
	cout << elem << ” ” ;
}

输出:

23 56 89 981 1425

上述代码中,push_backemplace_back 进行了同样的操作:在vector 的末尾追加数据。

自定义类型

如下是一个 vector 的类型是用户自定义类型(类 或 结构体)的例子:

class AA {
	string ss;
 
public:
 
	AA(string st):ss(st) { }
 
	string getString( ) const { return ss; }
 
	~AA( ) { }
};
 
int main() {

	vector<AA> vecA={ AA(“String”) , “Gift” , AA(“New”) }; ///vecA intialization
 
	vecA.push_back( AA(“happy”) ) ; //AA object is appended
 
	vecA.emplace_back( “Crop” ) ; ///work fine
	 
	vecA.push_back( “Dome” ) ; ///work fine
	 
	for( auto elem:vecA )
	{
		cout << elem.getString() << ” ” ;
	}
 
	cin.get( ) ;
	return 0 ;
}

输出:

String Gift New Happy Dome

自定义类型的构造函数只有一个参数时,push_backemplace_back 都可以直接传递原始数据类型,因为它们都会为该参数创建对象。

如果 vector 类型的构造函数接受一个以上的参数,那么传递给 emplace_back 的参数必须与这些参数 typw 匹配,如果参数类型不匹配,就无法调用构造函数,因此也就无法创建该类型的对象。

class BB {
	int i;
	string st;
 
public:
	BB(int ii , string ss ) : i(ii),st(ss) { }
 
	~BB( ) { }
};
 
vector<BB> vec;
 
vec.emplace_back( 89 , “New” ); //work fine
 
vec.emplace_back( 78 ) ; //error! requires second string argument
 
vec.emplace_back( “Monkey”, 890 ); //error! arguments does not match

如果发生重新分配,则迭代器、指针和引用无效

只有在发生重新分配时,该函数才会使指向 vector 的迭代器、指针和引用失效;如果没有发生重新分配,迭代器、指针和引用仍然有效。只有当 size 大于 vector 的 capacity 时,才会进行重新分配。

vector<int> vec;

vec.reserve( 3 ) ;
 
vector<int>::iterator vecIt = vec.begin( ) ;
 
vec.emplace_back(90);
vec.emplace_back(120);
vec.emplace_back(910);
 
cout << *vecIt << endl ;//iterator is still valid
 
vec.emplace_back( 4560 );
 
cout << *vecIt ; //undefined

代码中连续三次调用 emplace_back 不会重新分配存储空间,因为预留了三个对象的存储空间。但是在第四次调用 emplace_back 时,由于 size > capacity,因此发生重新分配。一旦发生重新分配,存储空间就有了新的内存地址,但迭代器 vecIt 仍然指向先前的存储空间,因此它失效。因此,使用 vecIt 访问内存是未定义的。

3、push_back VS emplace_back

尽管 push_backemplace_back 的唯一用途是在 vector 的末尾添加数据,但是它们也存在一些区别。最微小的区别是 push_back 从它创建开始就是标准 C++ 的一部分,但是 emplace_back 是在 C++11 的时候新加入的。

区别1:如果构造函数接受多个参数,push_back 只接受该类型的唯一对象,而 emplace_back 则接受该类型构造函数的参数。

vector 类型是用户自定义的类型:类或结构体,并且该类型的构造函数接受一个以上的参数时,在这种情况下,调用 push_back 函数需要传递一个该类型的对象。但在调用 emplace_back 时,我们只需传递构造函数类型的参数,而无需传递对象本身。

请注意,只有当构造函数接受一个以上参数时,才会出现这种差异。在只接受一个参数的构造函数中,当调用 push_back 时,我们可以传递构造函数类型的参数,而不是传递对象。在只有一个参数的构造函数中,push_back 接受的是原始数据而不是对象,这是由于 C++11 版本的 push_back 函数所致。C++11 版本允许根据传递的参数构建对象,然后将其推入 vector 容器。

如果构造函数接受两个或多个参数,则必须明确传递该类型的对象。

代码示例:构造函数只接受一个参数

class Test {
	int i ;
 
public:
	Test(int ii): i(ii) { } //constructor
 
	int get const() { return i; }
 
	~Test( ) { }
};
 
int main( ) {
	vector<int> vec={ 21 , 45 };
 
	vec.push_back( Test(34) ) ; //Appending Test object by passing Test object
 
	vec.push_back( 901 ) ; //Appending Test object but int data is passed,work fine
	 
	vec.emplace_back( Test(7889) ); //work fine
	 
	vec.emplace_back( 4156 ) ; //work fine
	 
	for( auto elem:vec ) {
		cout << elem.get() << ” ” ;
	}
	 
	cin.get( );
	return 0;
}

输出:

21 45 34 901 7889 4156

代码示例:构造函数接收两个参数

class New {
	int i;
	string st;
public:
	New(int ii, string s): i(ii) , st(s) { }
	 
	int getInt const() { return i; }
	 
	string getString const () { return st; }
	 
	~New( ) { }
};
 
int main( ) {
	vector<int> vec={ {21,”String”} , New{45 , “tinger”} } ;
	 
	vec.push_back( New(34 , “Happy” ) ) ; //Appending Test object
	 
	vec.push_back( 901 , “Doer” ) ; //Error!!
	 
	vec.emplace_back( New(78 , “Gomu gomu” ) ); //work fine
	 
	vec.emplace_back( 41 , “Shanks” ) ; //work fine
	 
	for( auto elem:vec ) {
		cout<< elem.getInt( ) << ” ” << elem.getString( ) << endl ;
	}
	 
	cin.get( ) ;
	return 0 ;
}

输出:

21 String
45 Tinger
34 Happy
78 Gomu gomu
41 Shanks

第一次 push_back 调用成功是因为我们传递了一个 "New "对象,但第二次 push_back 调用失败是因为 push_back 无法接受两个参数。另一方面,emplace_back 可以接受传递给它的两个参数(第 25 行)。

在接收参数时,emplace_back 会调用构造函数创建一个 New 对象,并将该对象追加到 vector 中,因此调用成功。

底线是,如果使用 push_back,而类型是 "类 "或 “结构体”,且构造函数只接受一个参数,那么就可以传递类的数据,而不用明确传递对象。但是,如果类的构造函数接受一个以上的参数,则只允许传递类的对象。

emplace_back 函数中,无论类是否接受一个或多个参数,你都可以传递对象或类的构造函数接受的数据类型,无论哪种方式,都可以正常工作。我的建议是,你应该优先使用 emplace_back,而不是 push_back

区别2:效率

在这里,"效率 "一词可以有不同的含义,我们将把它理解为 更快地运行代码:产生更少的开销。首先,让我们看看当 vector 类型是内置类型时的情况,然后再看看用户定义类型的情况。

built-in type

如果是内置类型,push_backemplace_back 在效率上没有区别。

User-defined type

如果 vector 类型是类或结构,即用户自定义类型,那么在这种情况下,emplace_back 比 push_back 函数更有效,为什么?

当类型是用户自定义类型时调用 push_back

如果我们尝试直接(在对象创建之前)使用 push_back 将对象追加到 vector 中,那么在此过程中会首先创建一个临时对象。在创建临时对象的过程中会发生三个步骤:

  1. 调用构造函数创建临时对象
  2. 该临时对象复制到 vector
  3. 复制对象后,会调用 destructor 来销毁临时对象。

调用 push_back 时发生的三个过程的验证结果在后文的 "旁注 "部分。

当类型是用户自定义类型时调用 emplace_back

如果使用 emplace_back,则不会创建临时对象,而是直接在 vector 中创建对象。使用 emplace_back,可以避免创建无关的临时对象。因此,性能得到了提升。

class Dat {
	int i;
 
public:
	Dat(int ii):i(ii) { }
	 
	~Dat( ) { }
};
 
vector<Dat> vec;
 
vec.push_back( Dat(89) ); //efficiency lesser
 
vec.push_back( 67 ); //Same as above efficiency is lesser
 
vec.emplace_back( 890 ); //efficiency more

在第一次 push_back调用(第 12 行)和第二次 push_back 调用(第 14 行)中,会出现上述三个步骤,因此性能会降低。

emplace_back 调用中,只发生第一步,因此性能得到提高。

class Bat {
	int i ;
	string ss ;
	char c ;
 
public:
	Dat(int ii , string s, char cc):i(ii) , ss(s) , c(cc) { }
	 
	~Dat( ) { }
};
 
int main () {
	Bat b1( 23 , "S" ,  'd');
	
	vector<Bat> v;
	
	v.push_back( b1 ); //Perforamce same as below
	
	v.empalce_back( 34 , "New" , 'D' ); //Perforamce same as above
	 
	v.push_back( Bat(90 , "String" , 'P') ); //Perforamce lesser
	 
	v.emplace_back( 890 , "true" , 'O' ); //No change in performance

}

在第一次 push_back 调用(第 17 行)中,我们只是传递已经创建的对象,因此不需要临时创建对象,因此性能与 emplace_back 调用相同。

在第二个 push_back 调用(第 21 行)中,需要创建临时对象,因此效率较低。

下面的图示可能会帮助你更好地理解。

在这里插入图片描述

emplace_back 函数调用中省略了复制过程。

旁注:验证调用 push_back 时发生的三个步骤

class A{
public:
	 A() { cout<<"A constructor called!!"; }
	 ~A() { cout<<"\nA destructor called!!"; }
};
 
int main()
{
	vec<A>v ; 
	 
	v.push_back( 78 );
	 
	/** or 
	v.psuh_back( A(890) ); //The output will be same 
	***/
	 
	cin.get();
	retrun 0;
}

输出:

A constructor called!!
A destructor called!!

调用构造函数创建临时对象,然后将临时对象复制到 vector 的存储空间中。最后调用析构函数销毁临时对象。程序输出结果证实了这一点。

如果你使用 emplace_back 运行程序:

v.emplace_back(23);

输出:

Constructor called

析构函数并未被调用。

4、参考

  • vector::emplace_back
  • vector::push_back
  • C++ difference between emplace_back and push_back function

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/788488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一分钟学一个 Linux 命令 - rm

前言 大家好&#xff0c;我是 god23bin&#xff0c;欢迎回到咱们的《一分钟学一个 Linux 命令》系列&#xff0c;今天我要讲的是一个比较危险的命令&#xff0c;rm 命令&#xff0c;没错&#xff0c;你可以没听过 rm 命令&#xff0c;但是删库跑路你不可能没听过吧&#xff1f…

RISCV -3 RV32I/RV64I基本整型指令集

RISCV -3 RV32I/RV64I基本整型指令集 1 RV32I Base Integer Instruction Set1.1 Programmers’ Model for Base Integer ISA1.2 Base Instruction Formats1.3 Immediate Encoding Variants1.4 Integer Computational Instructions1.4.1 Integer Register-Immediate Instruction…

25-30天每日强训选择题改错解析

int i5; int s(i)(i)(i–)(–i); s( )//s 的值是什么&#xff1f; A 28 B 25 C 21 D 26 E 24 F 23 正确答案&#xff1a; E 5775 24 或者 --在后先不变化数值 -- 在前先变化再运算 以下哪项不属于java类加载过程&#xff1f; A 生成java.lang.Class对象 B int类型对象成…

【Vue】day04-组件通信

day04 一、学习目标 1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法 父传子 子传父 非父子通信&#xff08;扩展&#xff09; 3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xf…

Windows下达梦数据库图形化安装、初始化数据库及连接

文章目录 前言一、达梦数据库安装1、下载安装包2、解压3、安装 二、初始化数据库三、连接数据库1、客户端工具2、输入连接信息3、成功连接 总结 前言 本节将介绍达梦数据库的图形化界面安装的细节&#xff0c;本节以Win11系统及DM8为基础进行讲解&#xff0c;虽然是图形化安装…

5. Bean 的作用域和生命周期

目录 1. Bean 被修改的案例 2. 作用域定义 2.1 Bean 的 6 种作用域 singleton prototype request session application&#xff08;了解&#xff09; websocket &#xff08;了解&#xff09; 单例作用域&#xff08;singleton&#xff09;VS 全局作用域&#xff08;…

企业知识管理系统安全是重中之重

企业开展知识管理工作的益处是全方位的&#xff0c;效果能从业务的各方面得到体现&#xff0c;最终效果就是企业竞争力的提升与企业经营业绩的提升。 知识管理系统的意义在于&#xff0c;构建系统的知识库&#xff0c;对纷杂的知识内容&#xff08;方案、策划、制度等&#xf…

【业务功能篇51】对象复制的三种方式 工具类Orika、反射、BeanUtils浅拷贝

业务场景&#xff1a; 设计规范前提下&#xff0c;我们数据层传输承载的是用DTO&#xff0c;而到控制层返回给前端会对应定义一个VO对象&#xff0c;比如是一个问题单数据集合list<DTO>,数据层接收的是DTO对对象&#xff0c;到控制层接收后需要转换成list<VO>,这里…

项目中如何使用文件IO?【大学学了好几门语言都有IO,到底怎么用?】

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException;public class TestFile {public static void main(String[] args) throws IOException {// 通过这个简单的程序, 把一个文件的内容读取出…

Docker Compose 容器编排

Docker compose Docker compose 实现单机容器集群编排管理&#xff08;使用一个模板文件定义多个应用容器的启动参数和依赖关系&#xff0c;并使用docker compose来根据这个模板文件的配置来启动容器&#xff09; 通俗来说就是把之前的多条docker run启动容器命令 转换为docker…

关于云服务器ECS、宝塔的安装配置以及图床的使用

一、阿里云服务器的申请以及宝塔的安装 安装配置服务器的原理&#xff1a; step1&#xff1a;地址栏输入阿里云服务器官网地址 step2&#xff1a;在首页依次点击以下内容&#xff1a; step3&#xff1a;选择立即购买&#xff0c;并填写以下内容&#xff1a; step4&#xff1a…

6.运算符

6.1赋值运算符 ➢已经学过的赋值运算符&#xff1a; ➢其他赋值运算符&#xff1a; 、-、*、/、% 6.2 一元运算符 众多的JavaScript的运算符可以根据所需表达式的个数, 分为一元运算符、二元运算符、三元运算符 ●二元运算符: 例&#xff1a;let num1020 ●一元运算符: 例…

Vue3输入框(Input)

APIs 参数说明类型默认值必传width输入框宽度string | number‘100%’falseaddonBefore设置前置标签string | slot‘’falseaddonAfter设置后置标签string | slot‘’falseallowClear可以点击清除图标删除内容booleanfalsefalsepassword是否启用密码框booleanfalsefalsedisabl…

CSS3 Flexbox

Flex 是 Flexible Box 的缩写&#xff0c;意为弹性盒子布局。 CSS3中一种新的布局模式&#xff1a;W3C在2009年提出的一种布局方案&#xff0c;一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。其目的是提供一种更加有效的方式来对一个容器…

回收站不见了?正确的2个操作方法!

大家有没有遇到回收站不见了的情况啊&#xff1f;真的很崩溃&#xff0c;我误删了一个比较重要的文件&#xff0c;想在回收站中把它还原&#xff0c;才发现我的回收站不见了&#xff01;这可咋整啊&#xff1f; 回收站是电脑操作系统中一个比较重要的功能&#xff0c;它可以帮助…

Ceph简介和特性

Ceph是一个多版本存储系统&#xff0c;它把每一个待管理的数据流(例如一个文件) 切分为一到多个固定大小的对象数据&#xff0c;并以其为原子单元完成数据存取。 对象数据的底层存储服务是由多个主机 (host) 组成的存储集群&#xff0c;该集群也被称之为 RADOS (ReliableAutoma…

DS18B20的原理及实例代码(51单片机、STM32单片机)

一、DS18B20介绍 DS18B20数字温度传感器是DALLAS公司生产的单总线器件&#xff0c;用它来组成一个测温系统具有线路简单&#xff0c;体积小&#xff0c;在一根通信线上可以挂很多这样的数字温度传感器&#xff0c;十分方便。 温度传感器种类众多&#xff0c;应用在高精度、高可…

快排、二路归并疑难杂症

蒟蒻小♥复习机试&#xff0c;记录一些疑点和注意点。 细节见代码注释 快排 快排中的边界条件判断需保证i<j&#xff0c;即满足label基准左边的数均小于右边的数。<的判断可能让子问题求解陷入死循环。 #include <iostream> #include <stdio.h> #include …

C++笔记之STL的sort使用第三个参数来自定义排序

C笔记之STL的sort使用第三个参数来自定义排序 code review! 文章目录 C笔记之STL的sort使用第三个参数来自定义排序1.方法一&#xff1a;使用比较函数(其实是使用函数指针)作为std::sort()的第三个参数来排序2.方法二&#xff1a;使用lambda表达式作为std::sort()的第三个参数…

IO进程线程day1(2023.7.25)

一、Xmind整理&#xff1a; 什么是IO&#xff1a; 文件IO函数与标准IO函数&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;标准IO函数的简单示例 scanf: if(OS Linux) {去调用Linux的文件IOread(); } else if(OS windows) {去调用windows的文件IOfread(); …