跳到主要内容
C++11 核心特性详解:列表初始化、右值引用与移动语义 | 极客日志
C++ 算法
C++11 核心特性详解:列表初始化、右值引用与移动语义 介绍 C++11 核心新特性,包括统一列表初始化方式、std::initializer_list 用法、左值与右值的区别及右值引用语法。重点讲解移动语义(移动构造与赋值)如何优化资源管理,以及完美转发机制。此外涵盖可变参数模板、Lambda 表达式语法与捕获列表、Function 包装器与 Bind 绑定器等实用工具,并对比新旧标准在 STL 容器及类默认成员函数上的变化。
协议工匠 发布于 2026/3/28 更新于 2026/6/15 40 浏览C++ 学习参考文档
1. C++ 发展历史
2. 列表初始化
2.1 C++98 传统的大括号初始化
C++98 中一般数组和结构体可以用 {} 进行初始化。
2.2 C++11 中的 {} 初始化
C++11 以后想统一初始化方式,试图实现一切对象皆可用 {} 初始化,{} 初始化也叫做列表初始化。
内置类型支持,自定义类型也支持。自定义类型本质是类型转换,中间会产生临时对象,最后优化后变成直接构造。
{} 初始化的过程中,可以省略掉 =。
C++11 列表初始化的本意是想实现一个大统一的初始化方式,其次它在有些场景下带来不少便利,如容器 push/inset 多参数构造的对象时,{} 初始化会很方便。
struct Point { int _x; int _y; };
class Date {
public :
Date (int year = 1 , int month = 1 , int day = 1 ) :_year(year), _month(month), _day(day) { cout << "Date(int year, int month, int day)" << endl; }
Date (const Date& d) :_year(d._year), _month(d._month), _day(d._day) { cout << "Date(const Date& d)" << endl; }
private :
int _year; int _month; int _day;
};
Date func () {
return {};
}
int main () {
array1[] = { , , , , };
array2[ ] = { };
Point p = { , };
;
Date d2 = ;
Date d5 = { , , };
Date d6{ , , };
Date d7{};
( );
({ , , });
i = ;
j = { };
k{ };
m{};
;
}
int
1
2
3
4
5
int
5
0
1
2
Date d1 (2025 , 11 , 15 )
2025
2025
11
15
2025
11
15
Insert
2025
Insert
2025
11
15
int
0
int
1
int
2
int
return
0
2.3 C++11 中的 std::initializer_list int main () {
vector<int > v1 = { 1 , 2 , 3 , 4 };
vector<int > v2{ 1 , 2 , 3 , 4 , 5 , 6 , 6 , 7 , 7 };
map<string, string> dict = { {"sort" , "排序" }, {"string" , "字符串" } };
v1 = { 10 , 20 , 30 };
auto il = { 10 , 20 , 30 };
cout << typeid (il).name () << endl;
std::initializer_list<int > mylist;
mylist = { 10 , 20 , 30 };
cout << sizeof (mylist) << endl;
int i = 0 ;
cout << mylist.begin () << endl;
cout << mylist.end () << endl;
cout << &i << endl;
return 0 ;
}
3. 右值引用和移动语义 C++98 的 C++ 语法中就有引用的语法,而 C++11 中新增了的右值引用语法特性,C++11 之后我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。
3.1 左值和右值
左值 :是一个表示数据的表达式(如变量名或解引用的指针),一般是有持久状态,存储在内存中,我们可以获取它的地址。左值可以出现赋值符号的左边,也可以出现在赋值符号右边。定义时 const 修饰符后的左值,不能给它赋值,但是可以取它的地址。
右值 :也是一个表示数据的表达式,要么是字面值常量,要么是表达式求值过程中创建的临时对象等。右值可以出现在赋值符号的右边,但是不能出现在赋值符号的左边,右值不能取地址。
值得一提的是,左值的英文简写为 lvalue,右值的英文简写为 rvalue。现代 C++ 中,lvalue 被解释为 locator value 的缩写,可意为存储在内存中、有明确存储地址可以取地址的对象;而 rvalue 被解释为 read value,指的是那些可以提供数据值,但是不可以寻址,例如:临时变量,字面量常量,存储于寄存器中的变量等。也就是说左值和右值的核心区别就是能否取地址。
int main () {
int * p = new int (0 );
int b = 1 ;
const int c = b;
*p = 10 ;
string s ("11111111111111" ) ;
s[0 ] = 'x' ;
cout << &p << endl;
cout << &b << endl;
cout << &c << endl;
cout << &(*p) << endl;
cout << &s << endl;
cout << (void *)&s[0 ] << endl;
double x = 1.1 , y = 2.2 ;
10 ;
x + y;
fmin (x, y);
string ("1111" );
return 0 ;
}
3.2 左值引用和右值引用
Type& r1 = x; Type&& rr1 = y; 第一个语句就是左值引用,左值引用就是给左值取别名,第二个就是右值引用,同样的道理,右值引用就是给右值取别名。
左值引用不能直接引用右值,但是 const 左值引用可以引用右值。
右值引用不能直接引用左值,但是右值引用可以引用 move(左值)。
template <class T> typename remove_reference<T>::type&& move(T&& arg); 是库里面的一个函数模板,本质内部是进行强制类型转换,当然他还涉及一些引用折叠的知识。
需要注意的是变量表达式都是左值属性,也就意味着一个右值被右值引用绑定后,右值引用变量表达式的属性是左值。
语法层面看,左值引用和右值引用都是取别名,不开空间。从汇编底层角度看,r1 和 rr1 底层都是用指针实现的,没什么区别。
int main () {
int * p = new int (0 );
int b = 1 ;
const int c = b;
*p = 10 ;
string s ("11111111111111" ) ;
s[0 ] = 'x' ;
double x = 1.1 , y = 2.2 ;
int & r1 = b;
int *& r2 = p;
int & r3 = *p;
string& r4 = s;
char & r5 = s[0 ];
int && rr1 = 10 ;
double && rr2 = x + y;
double && rr3 = fmin (x, y);
string&& rr4 = string ("1111" );
const int & rx1 = 10 ;
const double & rx2 = x + y;
const double & rx3 = fmin (x, y);
const string& rx4 = string ("11111" );
int && rrx1 = move (b);
int *&& rrx2 = move (p);
int && rrx3 = move (*p);
string&& rrx4 = move (s);
string&& rrx5 = (string&&)s;
int && rrrx1 = move (rrx1);
return 0 ;
}
3.3 引用延长生命周期 右值引用可用于为临时对象延长生命周期,const 的左值引用也能延长临时对象生存期,但这些对象无法被修改。
class A {
public :
A () { cout << "A()" << endl; }
~A () { cout << "~A()" << endl; }
};
int main () {
A aa1;
const A& ref1 = A ();
A&& ref2 = A ();
cout << "main end" << endl;
return 0 ;
}
3.4 左值和右值的参数匹配
C++98 中,我们实现一个 const 左值引用作为参数的函数,那么实参传递左值和右值都可以匹配。
C++11 以后,分别重载左值引用、const 左值引用、右值引用作为形参的 f 函数,那么实参是左值会匹配 f(左值引用),实参是 const 左值会匹配 f(const 左值引用),实参是右值会匹配 f(右值引用)。
右值引用变量在用于表达式时属性是左值,这个设计这里会感觉很怪,下一小节我们讲右值引用的使用场景时,就能体会这样设计的价值了。
void f (int & x) { cout << "左值引用重载 f(" << x << ")\n" ; }
void f (const int & x) { cout << "const 的左值引用重载 f(" << x << ")\n" ; }
void f (int && x) { cout << "右值引用重载 f(" << x << ")\n" ; }
int main () {
f (10 );
int a = 20 ;
f (a);
const int b = 20 ;
f (b);
int && x = 1 ;
f (x);
f (move (x));
return 0 ;
}
3.5 右值引用和移动语义的使用场景
3.5.1 左值引用主要使用场景回顾 左值引用主要使用场景是在函数中左值引用传参和左值引用传返回值时减少拷贝,同时还可以修改实参和修改返回对象的值。左值引用已经解决大多数场景的拷贝效率问题,但是有些场景不能使用传左值引用返回,如 addStrings 和 generate 函数,C++98 中的解决方案只能是被迫使用输出型参数解决。那么 C++11 以后这里可以使用右值引用做返回值解决吗?显然是不可能的,因为这里的本质是返回对象是一个局部对象,函数结束这个对象就析构销毁了,右值引用返回也无法改变对象已经析构销毁的事实。
3.5.2 移动构造和移动赋值
移动构造函数是一种构造函数,类似拷贝构造函数,移动构造函数要求第一个参数是该类类型的引用,但是不同的是要求这个参数是右值引用,如果还有其他参数,额外的参数必须有缺省值。
移动赋值是一个赋值运算符的重载,他跟拷贝赋值构成函数重载,类似拷贝赋值函数,移动赋值函数要求第一个参数是该类类型的引用,但是不同的是要求这个参数是右值引用。
对于像 string/vector 这样的深拷贝的类或者包含深拷贝的成员变量的类,移动构造和移动赋值才有意义,因为移动构造和移动赋值的第一个参数都是右值引用的类型,他的本质是要'窃取'引用的右值对象的资源,而不是像拷贝构造和拷贝赋值那样去拷贝资源,从而提高效率。
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <assert.h>
#include <string.h>
#include <algorithm>
using namespace std;
namespace bit {
class string {
public :
typedef char * iterator;
typedef const char * const_iterator;
iterator begin () { return _str; }
iterator end () { return _str + _size; }
const_iterator begin () const { return _str; }
const_iterator end () const { return _str + _size; }
string (const char *) :_size(strlen (str)), _capacity(_size) {
cout << "string(char* str)-构造" << endl;
_str = new char [_capacity + 1 ];
strcpy (_str, str);
}
void swap (string& s) {
::swap (_str, s._str);
::swap (_size, s._size);
::swap (_capacity, s._capacity);
}
string (const string& s) {
cout << "string(const string& s) -- 拷贝构造" << endl;
reserve (s._capacity);
for (auto ch : s) { push_back (ch); }
}
string (string&& s) {
cout << "string(string&& s) -- 移动构造" << endl;
swap (s);
}
string& operator =(const string& s) {
cout << "string& operator=(const string& s) -- 拷贝赋值" << endl;
if (this != &s) {
_str[0 ] = '\0' ; _size = 0 ;
reserve (s._capacity);
for (auto ch : s) { push_back (ch); }
}
return *this ;
}
string& operator =(string&& s) {
cout << "string& operator=(string&& s) -- 移动赋值" << endl;
swap (s);
return *this ;
}
~string () {
delete [] _str;
_str = nullptr ;
}
char & operator [](size_t pos) {
assert (pos < _size);
return _str[pos];
}
void reserve (size_t n) {
if (n > _capacity) {
char * tmp = new char [n + 1 ];
if (_str) { strcpy (tmp, _str); delete [] _str; }
_str = tmp;
_capacity = n;
}
}
void push_back (char ch) {
if (_size >= _capacity) {
size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2 ;
reserve (newcapacity);
}
_str[_size] = ch; ++_size;
_str[_size] = '\0' ;
}
string& operator +=(char ch) { push_back (ch); return *this ; }
const char * c_str () const { return _str; }
size_t size () const { return _size; }
private :
char * _str = nullptr ;
size_t _size = 0 ;
size_t _capacity = 0 ;
};
string addStrings (string num1, string num2) {
string str;
int end1 = num1. size () - 1 , end2 = num2. size () - 1 ;
int next = 0 ;
while (end1 >= 0 || end2 >= 0 ) {
int val1 = end1 >= 0 ? num1[end1--] - '0' : 0 ;
int val2 = end2 >= 0 ? num2[end2--] - '0' : 0 ;
int ret = val1 + val2 + next;
next = ret / 10 ;
ret = ret % 10 ;
str += ('0' + ret);
}
if (next == 1 ) str += '1' ;
reverse (str.begin (), str.end ());
cout << &str << endl;
return str;
}
}
int main () {
bit::string s1 ("xxxxx" ) ;
bit::string s2 = s1;
bit::string s3 = bit::string ("yyyyy" );
bit::string s4 = move (s1);
cout << "******************************" << endl;
return 0 ;
}
3.5.3 右值引用和移动语义解决传值返回问题 编译器优化(RVO/NRVO)在某些情况下会将拷贝构造优化为直接构造。在 debug 模式下通常能看到两次拷贝,release 模式下可能合三为一变为直接构造。Linux 下可使用 g++ test.cpp -fno-elideconstructors 关闭构造优化来观察未优化的行为。
3.6 类型分类
C++11 以后,进一步对类型进行了划分,右值被划分为纯右值 (prvalue) 和将亡值 (xvalue)。
纯右值 :指那些字面值常量或求值结果相当于字面值或是一个不具名的临时对象。如:42、true、nullptr 或者类似 str.substr(1, 2)、str1 + str2 传值返回函数调用,或者整形 a、b,a++,a+b 等。
将亡值 :是指返回右值引用的函数的调用表达式和转换为右值引用的转换函数的调用表达,如 move(x)、static_cast<X&&>(x)。
泛左值 (glvalue) :泛左值包含将亡值和左值。
3.7 引用折叠
C++ 中不能直接定义引用的引用如 int& && r = i;,这样写会直接报错,通过模板或 typedef 中的类型操作可以构成引用的引用。
通过模板或 typedef 中的类型操作可以构成引用的引用时,这时 C++11 给出了一个引用折叠的规则:右值引用的右值引用折叠成右值引用,所有其他组合均折叠成左值引用。
像 f2 这样的函数模板中,T&& x 参数看起来是右值引用参数,但是由于引用折叠的规则,他传递左值时就是左值引用,传递右值时就是右值引用,有些地方也把这种函数模板的参数叫做万能引用。
template <class T> void f1 (T& x) {}
template <class T> void f2 (T&& x) {}
int main () {
typedef int & lref;
typedef int && rref;
int n = 0 ;
lref& r1 = n;
lref&& r2 = n;
rref& r3 = n;
rref&& r4 = 1 ;
f1 <int >(n);
f1 <int >(0 );
f1 <int &>(n);
f1 <int &&>(n);
f2 <int >(n);
f2 <int &>(n);
f2 <int &&>(n);
return 0 ;
}
template <class T> void Function (T&& t) {
int a = 0 ;
T x = a;
cout << &a << endl;
cout << &x << endl << endl;
}
int main () {
Function (10 );
int a;
Function (a);
Function (std::move (a));
const int b = 8 ;
Function (b);
Function (std::move (b));
return 0 ;
}
3.8 完美转发
Function(T&& t) 函数模板程序中,传左值实例化以后是左值引用的 Function 函数,传右值实例化以后是右值引用的 Function 函数。
但是结合我们在 5.2 章节的讲解,变量表达式都是左值属性,也就意味着一个右值被右值引用绑定后,右值引用变量表达式的属性是左值,也就是说 Function 函数中 t 的属性是左值,那么我们把 t 传递给下一层函数 Fun,那么匹配的都是左值引用版本的 Fun 函数。这里我们想要保持 t 对象的属性,就需要使用完美转发实现。
template <class T> T&& forward(typename remove_reference<T>::type& arg);
template <class T> T&& forward(typename remove_reference<T>::type&& arg);
完美转发 forward 本质是一个函数模板,他主要还是通过引用折叠的方式实现。
template <class T> void Function (T&& t) {
Fun (forward<T>(t));
}
int main () {
Function (10 );
int a;
Function (a);
Function (std::move (a));
const int b = 8 ;
Function (b);
Function (std::move (b));
return 0 ;
}
4. 可变参数模板
4.1 基本语法及原理
C++11 支持可变参数模板,也就是说支持可变数量参数的函数模板和类模板,可变数目的参数被称为参数包,存在两种参数包:模板参数包,表示零或多个模板参数;函数参数包:表示零或多个函数参数。
我们用省略号来指出一个模板参数或函数参数的表示一个包,在模板参数列表中,class...或 typename...指出接下来的参数表示零或多个类型列表;在函数参数列表中,类型名后面跟...指出接下来表示零或多个形参对象列表。
可变参数模板的原理跟模板类似,本质还是去实例化对应类型和个数的多个函数。
这里我们可以使用 sizeof...运算符去计算参数包中参数的个数。
4.2 包扩展
对于一个参数包,我们除了能计算他的参数个数,我们能做的唯一的事情就是扩展它,当扩展一个包时,我们还要提供用于每个扩展元素的模式,扩展一个包就是将它分解为构成的元素,对每个元素应用模式,获得扩展后的列表。
C++17 的折叠表达式已弃用旧版包扩展语法,推荐使用折叠表达式。
template <class ...Args> void Print (Args... args) {
((cout << args << " s" ), ...);
cout << "\n" ;
}
int main () {
Print ();
Print (1 );
Print (1 , string ("xxxxx" ));
Print (1 , string ("xxxxx" ), 2.2 );
return 0 ;
}
4.3 emplace 接口
C++11 以后 STL 容器新增了 emplace 系列的接口,emplace 系列的接口均为模板可变参数,功能上兼容 push 和 insert 系列,但是 emplace 还支持新玩法,假设容器为 container,emplace 还支持直接插入构造 T 对象的参数,这样有些场景会更高效一些,可以直接在容器空间上构造 T 对象。
emplace_back 总体而言是更高效,推荐以后使用 emplace 系列替代 insert 和 push 系列。
传递参数包过程中,如果是 Args&&... args 的参数包,要用完美转发参数包,方式如下 std::forward<Args>(args)...,否则编译时包扩展后右值引用变量表达式就变成了左值。
int main () {
list<bit::string> lt;
bit::string s1 ("111111111111" ) ;
lt.emplace_back (s1);
cout << "*********************************" << endl;
lt.emplace_back (move (s1));
cout << "*********************************" << endl;
lt.push_back ("111111111111" );
cout << "*********************************" << endl;
lt.emplace_back ("111111111111" );
cout << "*********************************" << endl;
return 0 ;
}
struct Date {
int _y; int _m; int _d;
Date (int y = 1 , int m = 1 , int d = 1 ) :_y(y), _m(m), _d(d) {}
};
#pragma once
namespace bit {
template <class T > struct list_node {
list_node<T>* _next;
list_node<T>* _prev;
T _data;
template <class X> list_node (X&& x = X()) :_next(nullptr), _prev(nullptr), _data(forward<X>(x)) { }
template <class ...Args> list_node (Args&& ...args) : _next(nullptr), _prev(nullptr), _data(forward<Args>(args)...) { }
};
}
int main () {
list<pair<bit::string, int >> lt1;
pair<bit::string, int > kv ("苹果" , 1 ) ;
lt1. emplace_back (kv);
lt1. emplace_back (move (kv));
lt1. emplace_back ("苹果" , 1 );
list<Date> lt;
Date d1{ 2025 , 11 , 18 };
lt.push_back (d1);
lt.emplace_back (2025 , 11 , 18 );
return 0 ;
}
5. 新的类功能
5.1 默认的移动构造和移动赋值
原来 C++ 类中,有 6 个默认成员函数:构造函数/析构函数/拷贝构造函数/拷贝赋值重载/取地址重载/const 取地址重载。C++11 新增了两个默认成员函数,移动构造函数和移动赋值运算符重载。
如果你没有自己实现移动构造函数,且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。
如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。
class Person {
public :
Person (const char * name = "张三" , int age = 18 ) :_name(name), _age(age) {}
private :
bit::string _name;
int _age;
};
int main () {
Person s1;
Person s2 = s1;
Person s3 = std::move (s1);
Person s4 ("xxx" , 18 ) ;
s4 = std::move (s2);
return 0 ;
}
5.2 成员变量声明时给缺省值 成员变量声明时给缺省值是给初始化列表用的,如果没有显示在初始化列表初始化,就会在初始化列表用这个缺省值初始化。
5.3 default 和 delete
C++11 可以让你更好的控制要使用的默认函数。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用 default 关键字显示指定移动构造生成。
如果能想要限制某些默认函数的生成,只需在该函数声明加上=delete 即可,该语法指示编译器不生成对应函数的默认版本,称=delete 修饰的函数为删除函数。
class Person {
public :
Person (const char * name = "张三" , int age = 18 ) :_name(name), _age(age) {}
Person (const Person& p) = delete ;
Person (Person&& p) = default ;
~Person () {}
private :
bit::string _name;
int _age;
};
5.5 final 与 override
5.6 委托构造函数 class Example {
public :
Example (int a, int b) :_x(a), _y(b) { cout << "目标构造函数\n" ; }
Example (int a) : Example (a, 0 ) { cout << "委托构造函数\n" ; }
int _x; int _y;
};
5.7 继承构造函数 class Base {
public :
Base (int x, double d) :_x(x), _d(d) {}
Base (int x) :_x(x) {}
Base (double d) :_x(d) {}
protected :
int _x = 0 ; double _d = 0 ;
};
class Derived : public Base {
public :
using Base::Base;
};
int main () {
Derived d1 (1 ) ;
Derived d2 (1.1 ) ;
Derived d3 (2 , 2.2 ) ;
return 0 ;
}
6. STL 中一些变化 STL 容器在 C++11 中增加了许多新特性,如 emplace 系列接口、initializer_list 支持等。
7. lambda
7.1 lambda 表达式语法 int main () {
auto add1 = [](int x, int y){return x + y; };
cout << add1 (1 , 2 ) << endl;
auto func1 = [] { cout << "hello bit" << endl; return 0 ; };
func1 ();
int a = 0 , b = 1 ;
auto swap1 = [](int & x, int & y) { int tmp = x; x = y; y = tmp; };
swap1 (a, b);
cout << a << ":" << b << endl;
return 0 ;
}
7.2 lambda 的应用 struct Goods {
string _name; double _price; int _evaluate;
Goods (const char * str, double price, int evaluate) :_name(str), _price(price), _evaluate(evaluate) {}
};
int main () {
vector<Goods> v = { { "苹果" , 2.1 , 5 }, { "香蕉" , 3 , 4 }, { "橙子" , 2.2 , 3 }, { "菠萝" , 1.5 , 4 } };
sort (v.begin (), v.end (), [](const Goods& gl, const Goods& gr) { return gl._price < gr._price; });
sort (v.begin (), v.end (), [](const Goods& gl, const Goods& gr) { return gl._price > gr._price; });
return 0 ;
}
7.3 lambda 的原理 Lambda 表达式本质上是一个闭包,编译器会将其转换为一个仿函数类。
7.4 捕捉列表 int x = 0 ;
auto func1 = []() { x++; };
class A {
public :
void func () {
int x = 0 , y = 1 ;
auto f1 = [=] { _a1++; return x + y + _a1 + _a2; };
auto f2 = [&] { x++; _a1++; return x + y + _a1 + _a2; };
auto f3 = [x, this ] { _a1++; return x + _a1 + _a2; };
}
private :
int _a1 = 0 ; int _a2 = 1 ;
};
int main () {
int a = 0 , b = 1 , c = 2 , d = 3 ;
auto func1 = [a, &b] { int ret = a + b; x++; return ret; };
auto func2 = [=] { int ret = a + b + c; return ret; };
auto func3 = [&] { a++; c++; d++; };
func3 ();
return 0 ;
}
8. 包装器
8.1 function std::function 是 C++11 引入的标准库中的一个通用多态函数包装器,定义在 <functional> 头文件中。它的主要作用是对可调用对象(callable objects)进行类型擦除和统一接口封装。
#include <functional>
int f (int a, int b) { return a + b; }
struct Functor { int operator () (int a, int b) { return a + b; } };
class Plus {
public :
static int plusi (int a, int b) { return a + b; }
double plusd (double a, double b) { return (a + b) * _n; }
Plus (int n = 10 ) :_n(n) {}
private : int _n; };
int main () {
function<int (int , int )> f1 = f;
function<int (int , int )> f2 = Functor ();
function<int (int , int )> f3 = [](int a, int b) {return a + b; };
vector<function<int (int , int )>> v;
v.push_back (f);
v.push_back (Functor ());
v.push_back ([](int a, int b) {return a + b; });
function<double (Plus*, double , double )> f5 = &Plus::plusd;
Plus ps;
cout << f5 (&ps, 1.1 , 1.1 ) << endl;
return 0 ;
}
8.2 bind bind 主要用来调整参数个数和参数顺序,placeholders 命名空间的 _1 _2 分别表示实参的第一个参数和第二个参数。bind 一般用于绑死一些固定参数。
#include <functional>
using placeholders::_1; using placeholders::_2;
int SubX (int a, int b, int c) { return (a - b - c) * 10 ; }
int main () {
auto f3 = bind (SubX, 10 , _1, _2);
cout << f3 (15 , 5 ) << endl;
auto f8 = bind (&Plus::plusd, Plus (), _1, _2);
cout << f8 (1.1 , 1.1 ) << endl;
return 0 ;
}
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online