跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++11 核心特性详解:初始化、移动语义与 Lambda 表达式

C++11 的核心新特性,涵盖从 C++98 到 C++11 的初始化语法变化(列表初始化与 std::initializer_list)、可变参数模板及 emplace 系列接口的高效插入、STL 新增容器(array、forward_list、tuple)的使用、类的新功能(移动语义、default/delete、final/override)、Lambda 表达式的语法与原理,以及 function 和 bind 包装器的应用场景。内容旨在帮助开发者掌握现代 C++ 编程范式,提升代码效率与可维护性。

DevStack发布于 2026/3/28更新于 2026/10/26100 浏览
C++11 核心特性详解:初始化、移动语义与 Lambda 表达式

1.从 C++98 到 C++11 的初始化

C++98 的{}初始化

C++98 中可以使用 {} 对数组和结构体进行初始化。

struct Triangle { int _a; int _b; int _c; };
int main() {
    // 用{}对数组和结构体进行初始化
    int arr1[] = {2, 4, 6, 8, 7};
    int arr2[10] = {3, 4, 5};
    Triangle t = {3, 4, 5};
    return 0;
}

C++11 列表初始化

列表初始化是 C++11 引入的初始化语法,通过花括号 {} 对所有对象进行统一初始化。

内置类型初始化:

// 直接列表初始化,可以省略掉 =
int x = {10};
int y{5};
double d{3.14};

自定义类型初始化: 对于自定义类型的初始化,本质上是类型转化,先构造临时对象,再用临时对象拷贝构造,编译器会直接优化为直接构造。

struct Triangle { int _a; int _b; int _c; };
Triangle t1 = {3, 4, 5};
Triangle t2{6, 8, 10};
// 引用临时对象需要加 const
const Triangle& t3 = {6, 6, 6};

列表初始化特点:

  1. 统一初始化语法:
    • 支持内类类型、自定义类型(类)和 STL 容器。
    • 避免窄化转换(narrowing conversion)。例如,float 转 int 会导致编译错误。
  2. 更简洁:
    • 和传统的构造函数初始化相比,代码更直观。

std::initializer_list

std::initializer_list 是 C++ 标准库中的一个类模板,用于表示一组以花括号 {} 括起来的初始值序列。

主要用于函数参数的接收,允许代码编写更灵活、简洁的代码。

特点:

  1. std::initializer_list 是一个轻量级的不可修改的对象,用于以数组形式存储初始化值。
  2. 它提供类似数组的访问方式,比如 .begin() 和 .end()。
  3. 适合传递数量不确定的参数。

限制:

  • std::initializer_list 的元素是不可修改的,只能读取。
  • 适用于较小规模的初始化列表,因为它的实现通常会生成临时数组,存在一定的性能开销。

STL 容器都增加了一个 initializer_list 的构造,目的是让 vector、list 等容器支持多参数构造。

不仅如此,容器的赋值也支持 initializer_list 的版本。

vector(initializer_list<value_type> il, const allocator_type& alloc = allocator_type());
list(initializer_list<value_type> il, const allocator_type& alloc = allocator_type());
map(initializer_list<value_type> il, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());

语法示例:

// 调用了 initializer_list 版本的构造
vector<int> v1({1, 2, 3, 4});
// 列表初始化,构造临时对象,再拷贝构造,但编译器会直接优化成构造(= 可以省略)
vector<int> v2 = {1, 2, 3, 4};
const vector<int>& v3 = {1, 2, 3, 4};
// pair 的{}的初始化和 map 的 initializer_list 构造结合
map<string, string> dict({{"apples", "苹果"}, {"index", "下标"}});
// initializer_list 版本的赋值重载
v1 = {4, 5, 6, 7};

std::initializer_list 和列表初始化的区别:

特性std::initializer_list列表初始化
引入版本C++11C++11
目的用于函数接收初始值列表统一初始化语法,增强灵活性
使用场景函数参数任意对象的初始化
实现机制内部通过临时数组存储直接调用构造函数
修改性不可修改支持修改

2.可变模板参数

可变参数模板是 C++11 引入的一种强大的模板功能,允许模板接受可变数量的模板参数,它为开发泛型代码提供了很大的灵活性,特别是在处理不同数量和类型的参数时。

定义方式

一个可变参数模板用 ... 表示可变参数,基本语法如下:

template<typename... Args>
void functionName(Args... args) {
    // 函数体
}
  • Args... 是一个模板参数包,表示零个或者多个模板参数,其原理与模板类似,本质还是去实例化对应类型和不同参数个数的多个函数。
  • args... 是一个函数参数包,表示零个或者多个模板参数,可以用 sizeof... 运算符去计算参数包中参数的个数,也可以使用左值引用和右值引用,与普通模板一样。

语法示例:计算函数参数包的个数。

template<class... Args>
void CountArgs(Args&&... args) // 右值引用
{
    cout << sizeof...(args) << endl;
}
int main() {
    CountArgs(); // 0 个
    CountArgs(1); // 1 个
    CountArgs(1, string("ABCD")); // 2 个
    CountArgs(1, string("ABCD"), vector<int>(10)); // 3 个
    return 0;
}

展开参数包

参数包需要展开才能使用,展开一个参数包就是将其分解成单个元素,需要在参数包的右边放置 ... 来完成触发。

有几种典型的方式去展开参数包:

1. 递归展开

void ShowList() {
    cout << endl;
    cout << "End of recursion" << endl;
}
template<class T, class... Args>
void ShowList(T x, Args... args) {
    cout << x << " ";
    // 递归调用
    ShowList(args...);
}
template<class... Args>
void PrintArgs(Args... args) {
    // 展开函数参数包
    ShowList(args...);
}
int main() {
    PrintArgs(1, 2, 5, 'A', "hello");
    return 0;
}

2. 使用折叠表达式(C++17)

template<class... Args>
void PrintArgs(Args... args) {
    (...,(cout << args << " ")); // 左折叠
    cout << endl;
}
int main() {
    PrintArgs(1, 2.5, "Hello", 'A');
    return 0;
}

emplace 系列接口

在 C++11 后,C++中的标准容器(如 vector、deque、map 等)新增了 emplace 系列的接口来高效插入元素,这个系列的接口均为可变参数模板,可以通过原地构造的方式,直接在容器的内存构造元素(in-place construction),避免不必要的拷贝或移动操作。

1. emplace 系列接口的优势:

  • 高效性:与 push_back 或 insert 相比,emplace 系列允许直接构造元素在容器的目标位置,避免了额外的拷贝或移动。
  • 灵活性:接受构造函数的参数,可以在容器中构造复杂的对象。

2. emplace 系列接口实现直接构造元素在容器的目标位置:

emplace 系列接口是通过完美转发来实现直接构造的。

  • emplace 接口接受可变参数 (Args&&... args),并使用 std::forward 将这些参数转发到目标类型的构造函数。
  • 这样,emplace 能够根据传入参数的具体类型(左值或右值)正确调用匹配的构造函数。

3. 相较于传统方法,emplace 系列接口具体高效的地方:

  • 在插入的对象存在时,传统方法(如 push_back 或 insert)与 emplace 系列的效率是一样的。
  • 传统方法(如 push_back 或 insert)在插入的对象不存在时,需要调用目标对象的构造函数创建临时对象,然后拷贝/移动到容器中。
  • emplace 系列接口可以接收不存在对象的构造函数的参数,直接在容器的内存中调用目标对象的构造函数,无需创建临时对象,避免了拷贝或移动操作。

具体例子:

// 用于存放 pair 的数组
vector<pair<string, int>> v;
// 传统方法
v.push_back(make_pair("hello", 1));
v.push_back({"world", 2});
// emplace 系列
v.emplace_back("happy", 3);

代码讲解:

  • push_back:无论是使用 make_pair 还是 {},本质上都是构造一个 pair 的临时对象,然后拷贝/移动到容器中。
  • emplace_back:直接将构造临时对象 pair 的参数传入,在函数内部,通过参数包的层层传入,最终在插入的目标位置调用 pair 的构造函数构造出 pair,从而避免了不必要的拷贝/移动操作。

4. emplace 系列与 push_back 和 insert 的对比:

接口特点适用场景
push_back先构造临时对象,再拷贝或移动到容器中简单场景,已有临时对象
emplace_back直接在容器尾部构造对象,避免拷贝/移动高效插入对象到尾部
insert先构造临时对象,再插入到指定位置在指定位置插入现有对象
emplace直接在指定位置构造对象,避免拷贝/移动在指定位置高效插入新对象

总结来说,emplace 系列接口为现代 C++ 提供了更高效、更灵活的容器操作方式,尤其适合复杂对象的构造与插入。

3.STL 的变化

C++11 之后,STL 新增了 array、forward_list、unordered_map、unordered_set、tuple 等容器,它们扩展了标准库容器的功能和使用场景。

以下介绍几个容器:

1. std::array

  • 特点:静态数组的封装类,具有固定大小。
  • 优势:支持 STL 接口(如迭代器),更安全、灵活,替代 C 风格数组。
  • 示例:
int main() {
    array<int, 4> arr = {1, 2, 3, 4};
    for (int n : arr) {
        cout << n << " ";
    }
    return 0;
}

2. std::forward_list

  • 特点:单向链表(比 std::list 更轻量)。
  • 优势:内存占用更小,适合简单链表操作。
  • 示例:
int main() {
    forward_list<int> flist = {1, 2, 3};
    flist.push_front(0); // 添加到头部
    for (int n : flist) {
        cout << n << " ";
    }
    return 0;
}

3. std::tuple

  • 特点:支持存储多个不同类型的值(扩展了 std::pair 功能)。
  • 优势:适合存储和返回多类型组合数据。
  • 示例:
int main() {
    tuple<int, string, double> t(1, "Hello", 3.14);
    cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t);
    return 0;
}

这些新增容器为开发者提供了更灵活、高效的工具来处理各种数据结构,同时也更贴合现代 C++ 的设计理念(如 RAII、泛型编程 等)。

4.类的新功能

移动构造和移动赋值

C++11 引入了右值引用(&&),从而实现了移动语义。移动构造函数和移动赋值函数可以实现资源的转移,而非拷贝。

1. 移动构造(移动赋值)函数生成条件

当没有实现移动过构造函数并且没有实现析构函数、拷贝构造函数和赋值重载函数,编译器就会生成一个默认移动构造函数或者移动赋值函数。

2. 解析生成的移动构造(移动赋值)函数

  1. 对于内置类型成员进行浅拷贝。
  2. 对于自定义类型的成员,需要看这个成员有没有实现移动构造函数(移动赋值函数):
    • 如果有则调用该成员的移动构造函数(移动赋值函数)。
    • 如果没有就调用拷贝构造函数(赋值重载)。

示例:

class MyClass {
public:
    MyClass(vector<int> v = vector<int>()) : data(v) {}
    // 移动构造
    MyClass(MyClass&& mycl) noexcept : data(move(mycl.data)) {
        cout << "Move Constructor Called" << endl;
    }
    // 移动赋值
    MyClass& operator=(MyClass&& mycl) noexcept {
        if (this != &mycl) {
            data = move(mycl.data);
            cout << "Move Assignment Operator Called" << endl;
        }
        return *this;
    }
    void show() {
        for (auto e : data) {
            cout << e << " ";
        }
        cout << endl;
    }
private:
    vector<int> data;
};
int main() {
    // 转移匿名对象的资源
    MyClass mycl1 = move(MyClass({1, 2, 3, 4}));
    mycl1.show();
    // 转移 mycl2 的资源到 mycl3
    MyClass mycl2({1, 2, 3, 4});
    MyClass mycl3;
    mycl3 = move(mycl2);
    mycl2.show();
    mycl3.show();
    return 0;
}

3. 拷贝与移动的区别

特性拷贝构造/赋值移动构造/赋值
操作方式复制资源(通常深拷贝)转移资源的所有权
参数类型const T&(左值引用)T&&(右值引用)
性能较慢(需要额外资源分配)较快(资源直接转移)

移动构造函数和移动赋值运算符通过转移资源提高了程序的性能,特别是对于需要动态资源管理的类(如含有指针或动态容器的类)。它们利用右值引用(&&)和 std::move 来实现高效的资源管理,是现代 C++ 中优化性能的重要工具。

default 和 delete

1. 默认函数(=default)

允许显式声明默认构造函数、拷贝构造函数、移动构造函数和赋值重载函数等默认成员函数,这样编译器就会强制生成默认成员函数。

class MyClass {
public:
    MyClass() = default; // 使用默认构造函数
    MyClass(const MyClass&) = default; // 使用默认拷贝构造函数
};

2. 删除函数(=delete)

可以显式禁用默认成员函数,这样编译器就不会生成。

class MyClass {
public:
    MyClass() = default;
    MyClass(const MyClass&) = delete; // 禁止拷贝构造
};

final 和 override

1. final

用于禁止类被继承或者重写。

class Base {
public:
    virtual void func() final {} // 禁止进一步重写
};
class Derived : public Base {
    // void func() override {} // 编译错误
};

2. override

用于检测函数是否完成重写,没有完成则报错。

class Base {
public:
    virtual void func() {};
};
class Derived : public Base {
public:
    void func() override {
        // 确保是重写基类函数
        // ...
    }
};

5.lambda 表达式

Lambda 表达式是 C++11 中的一项重要特性,提供了一种更为简洁和灵活的方式来定义匿名函数或内联函数。这些函数可以在需要函数对象的地方作为参数传递,通常用于算法或函数式编程风格。

基本语法

[capture](parameters)-> return_type { function_body }
  • 捕获列表(capture):捕获外部变量,可以按值(=)或者按引用(&)捕获。
  • 参数列表(parameters):函数参数,可以为空。
  • 返回类型(-> return_type):指定返回值类型,一般省略。
  • 函数体({ function_body }):Lambda 表达式的主体,可以使用参数或者捕获而来的变量进行实际操作。

lambda 表达式本质上是一个匿名函数对象,在使用层面上没有类型可言,一般使用 auto 或者 模板参数定义的对象 去接受 lambda 对象。

示例 1:打印 hello world

int main() {
    auto hello = []()->void {
        cout << "hello world" << endl;
    };
    hello();
    return 0;
}
  • 捕获列表为空,表示不捕获任何变量。
  • 该 lambda 表达式 无参数且无返回值,执行打印 hello world 的操作。

示例 2:add 函数

int main() {
    auto add = [](int x, int y) {
        return x + y;
    };
    cout << add(2, 3) << endl;
}
  • 捕获列表为空,表示不捕获任何变量。
  • 该 lambda 表达式 有参数且有返回值,执行将两数相加的操作。

捕获列表

捕获列表的作用就是将外部的参数捕获,使得函数体可以使用外部的参数,捕获的方式一般有以下几种:

  1. 按值捕获([=]):将外部变量的值复制到 lambda 中,类似于函数的传值传参,修改 lambda 中的变量不会影响外部变量。
  2. 按引用捕获([&]):将外部变量的引用传递给 lambda,lambda 中修改的变量将反映到外部变量。
  3. 混合捕获([=, &x] 或 [&, x]):按值捕获所有外部变量的值,但按引用捕获 x;或按引用捕获所有外部变量的值,但按值捕获 x。
int x = 10, y = 20, z = 30;
// 按值捕获 x,y,但是捕获而来的变量默认是加了 const 修饰的,如果想要修改需要加 mutable
// 因为是按值捕获是一种拷贝,在 lambda 里修改了捕获而来的变量也不会传递到外部
auto sum1 = [x, y]() mutable {
    x = 10;
    return x + y;
};
// 按引用捕获 x,y,对 x,y 的修改可以传递到外部
auto sum2 = [&x, &y]() {
    return x + y;
};
// 按值捕获所有外部变量 x、y、z
auto sum3 = [=]() {
    return x + y + z;
};
// 按引用捕获所有外部变量 x、y、z
auto sum4 = [&]() {
    return x + y + z;
};
// 按值捕获所有外部变量,但按引用捕获 z
auto sum5 = [=, &z]() {
    return x + y + z;
};
// 按引用捕获所有外部变量,但按值捕获 z
auto sum6 = [&, z]() {
    return x + y + z;
};

lambda 原理

Lambda 表达式 在 C++ 中本质上是由编译器生成的类对象(类似于仿函数),这个类实现了 operator()(函数调用运算符),因此它行为类似于函数对象。

工作原理:

  1. 编译器生成类
    • 每个 Lambda 表达式 都对应一个编译器自动生成的类,其类名按照一定编译规则生成,保证不同的 lambda 表达式 生成的类名不同。
    • 捕获的外部变量会成为这个类的成员变量。
    • Lambda 的函数体会转化为 operator() 方法的实现。
  2. 实例化类对象
    • Lambda 表达式 在使用时,会生成这个类的一个对象。
    • 通过调用 operator(),执行 Lambda 的函数体。

Lambda 表达式 在现代 C++ 中是一个强大的工具,能够提高代码的灵活性和简洁性。它的应用场景广泛,从简单的算法自定义操作到复杂的回调和递归逻辑。理解其背后的原理(编译器生成匿名类)可以更好地掌握其用法和性能特性。

6.包装器

function

在 C++ 中,function 是一个通用的函数包装器,它能够储存、复制和调用任何可调用目标,包括普通函数、Lambda 表达式、函数对象以及成员函数。function 是 C++11 引入的一部分,位于 <functional> 头文件。

1. function 的定义

function 是一个类模板,语法如下:

template<class Ret, class... Args>
class function<Ret(Args...)>;

2. function 的功能

  • 包装可调用对象:function 可以保存普通函数、Lambda 表达式、函数对象(仿函数)或指向成员函数的指针。若不含任何可调用对象,则为空,调用空的 function 会抛出 std::bad_function_call 异常。
  • 类型擦除:无论目标对象的类型如何,function 都提供统一的接口调用。
  • 动态存储:允许在运行时选择不同的可调用目标。

3. 使用示例

int add(int x, int y) {
    return x + y;
}
struct divide {
    double operator()(double x, double y) {
        return x / y;
    }
};
class MyClass {
public:
    int subtract(int x, int y) const {
        return x - y;
    }
    static void Print() {
        cout << "hello world" << endl;
    }
};
int main() {
    // 包装普通函数
    function<int(int, int)> addfunc = add;
    cout << addfunc(2, 3) << endl; // 输出 5
    // 包装 lambda 表达式
    function<int(int, int)> multiplyfunc = [](int x, int y) {
        return x * y;
    };
    cout << multiplyfunc(3, 4) << endl; // 输出 12
    // 包装仿函数
    function<double(double, double)> dividefunc = divide();
    cout << dividefunc(6, 3) << endl; // 输出 2
    // 包装成员函数,成员函数要指定类域并且加&才能取地址
    // 还要注意隐式 this 指针的问题,传地址或者对象都可以
    function<int(MyClass*, int, int)> subtractfunc = &MyClass::subtract;
    MyClass mycl;
    cout << subtractfunc(&mycl, 7, 4) << endl; // 输出 3
    // 包装静态成员函数,静态成员函数没有 this 指针
    function<void()> Printfunc = &MyClass::Print;
    Printfunc(); // 打印 helloworld
    return 0;
}

function 在一些场景中,能够大幅简化代码,使得代码的可读性更高。就比如解决下面这道算法题:逆波兰表达式求值。

比较传统的写法:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for (auto e : tokens) {
            if (e != "+" && e != "-" && e != "*" && e != "/") st.push(stoi(e));
            else if (!st.empty()) {
                int x = st.top(); st.pop();
                int y = st.top(); st.pop();
                switch (e[0]) {
                    case '+': st.push(x + y); break;
                    case '-': st.push(y - x); break;
                    case '*': st.push(x * y); break;
                    case '/': st.push(y / x); break;
                }
            }
        }
        int ret = st.top(); st.pop();
        return ret;
    }
};

使用 function 的写法:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        // function 作为 map 的映射可调⽤对象的类型
        map<string, function<int(int, int)>> FuncMap = {
            {"+", [](int x, int y) { return x + y; }},
            {"-", [](int x, int y) { return x - y; }},
            {"*", [](int x, int y) { return x * y; }},
            {"/", [](int x, int y) { return x / y; }}
        };
        stack<int> st;
        for (auto& str : tokens) {
            if (FuncMap.count(str)) {
                int right = st.top(); st.pop();
                int left = st.top(); st.pop();
                int ret = FuncMap[str](left, right);
                st.push(ret);
            } else {
                st.push(stoi(str));
            }
        }
        return st.top();
    }
};

function 是通过函数包装器:支持普通函数、Lambda、仿函数和成员函数。 适合需要动态函数存储的场景:例如回调或事件系统。 性能权衡:灵活性带来一定的性能开销,在高性能场景下可优先考虑模板或直接调用。

bind

std::bind 是 C++ 标准库 functional 中的一个工具(函数模板),作用是将函数和参数绑定,生成一个新的可调用对象(函数对象),这个对象可以像普通函数一样调用。

语法

#include <functional>
auto new_func = std::bind(func, arg1, arg2, ...);
  • func:被绑定的目标函数,可以是普通函数、成员函数或者函数对象。
  • arg1, arg2, ...:绑定的参数。未绑定的参数用占位符 placeholders::_1,placeholders::_2 表示。

占位符

placeholders::_1,placeholders::_2 等占位符表示未绑定的参数,调用时需要提供对应的值。

  • placeholders::_1 表示第一个未绑定的参数。
  • placeholders::_2 表示第二个未绑定的参数。
  • 依次类推。

使用示例

void print(int a, int b) {
    cout << "a: " << a << ", b: " << b << endl;
}
class MyClass {
public:
    void display(int value) {
        cout << "Value: " << value << endl;
    }
};
struct Functor {
    void operator()(int x, int y) {
        cout << "x - y = " << x - y << endl;
    }
};
int main() {
    // 绑定普通函数
    auto bound_func = bind(print, 10, placeholders::_1);
    bound_func(20);
    // 绑定 lambda 表达式
    auto add = bind([](int x, int y) { return x + y; }, 10, placeholders::_1);
    cout << "add: " << add(30) << endl;
    // 绑定成员函数
    auto b_display = bind(&MyClass::display, MyClass(), placeholders::_1);
    b_display(20);
    // 绑定仿函数
    auto b_subtract = bind(Functor(), 100, placeholders::_1);
    b_subtract(50);
    return 0;
}

总结

  • bind 是一个强大的工具,适合绑定函数和参数,生成新的函数对象。
  • 使用占位符可以灵活地表示未绑定的参数。
  • 在现代 C++ 中,虽然 bind 仍然适用,但大多数场景更推荐使用 Lambda 表达式。

目录

  1. 1.从 C++98 到 C++11 的初始化
  2. C++98 的{}初始化
  3. C++11 列表初始化
  4. std::initializer_list
  5. 2.可变模板参数
  6. 定义方式
  7. 展开参数包
  8. emplace 系列接口
  9. 3.STL 的变化
  10. 4.类的新功能
  11. 移动构造和移动赋值
  12. default 和 delete
  13. final 和 override
  14. 5.lambda 表达式
  15. 基本语法
  16. 捕获列表
  17. lambda 原理
  18. 6.包装器
  19. function
  20. bind

更多推荐文章

查看全部
  • C++工具库之PugiXML使用指南
  • 基于 Claude Code 的 AI 内容创作自动化工作流实战
  • 网络安全专家常用的 9 大工具
  • Linux 动态库与静态库技术详解
  • C++ AVL 树原理与实现详解
  • VSCode Copilot 接入 OpenAI 兼容自定义模型方案
  • 声源定位算法基础:常规波束形成(CBF)原理
  • AI 帮我改 Bug:小厂架构师的 Agent 落地实战与反思
  • Android 照片墙效果实现:GridView 与 LruCache 优化
  • C++ 初阶核心:命名空间、输入输出与函数重载
  • 面向 C++ 开发的 Web 自动化测试入门:从概念到 Selenium 实战
  • 微信群智能管理:扣子机器人接入实战
  • 在 Cursor 中配置和使用 MCP 服务指南
  • Spring Boot 配置加载顺序详解
  • OpenClaw Session 机制详解:重置、压缩、剪枝与记忆管理
  • CentOS 7 安装配置 Ollama 及模型加载指南
  • 基于 AI 大模型与 Playwright 的 Web UI 自动化测试实践
  • 2026 年 AI 写作辅助工具精选:5 款主流软件深度评测
  • AI Agent 开发入门:零基础学习指南
  • 网络安全入门核心知识点与学习路径指南

相关免费在线工具

  • 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

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online