Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++】C++11风云再起:语法新纪元,性能新巅峰!

【C++】C++11风云再起:语法新纪元,性能新巅峰!

作者头像
HZzzzzLu
发布于 2024-12-26 01:03:38
发布于 2024-12-26 01:03:38
18100
代码可运行
举报
文章被收录于专栏:codingcoding
运行总次数:0
代码可运行

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

C++98的{}初始化

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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引入的初始化语法,通花括号 {} 对所有对象。 内置类型初始化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//直接列表初始化,可以省略掉 = 
int x = { 10 };
int y{ 5 };
double d{3.14}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 的构造,目的是让 vectorlist 等容器支持多参数构造。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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());

语法示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//调用了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++11

C++11

目的

用于函数接收初始值列表

统一初始化语法,增强灵活性

使用场景

函数参数

任意对象的初始化

实现机制

内部通过临时数组存储

直接调用构造函数

修改性

不可修改

支持修改

2.可变模板参数

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

定义方式

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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. 递归展开

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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++中的标准容器(如 vectordequemap 等)新增了 emplace 系列的接口来高效插入元素,这个系列的接口均为可变参数模板,可以通过原地构造的方式,直接在容器的内存构造元素(in-place construction),避免不必要的拷贝或移动操作。

1.emplace 系列接口的优势

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

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

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

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

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

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

具体例子

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//用于存放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 :直接将构造临时对象 piar 的参数传入,在函数内部,通过参数包的层层传入,最终在插入的目标位置调用 pair 的构造函数构造出 pair ,从而避免了不必要的拷贝/移动操作。
  1. emplace 系列与 push_backinsert 的对比 :

接口

特点

适用场景

push_back

先构造临时对象,再拷贝或移动到容器中

简单场景,已有临时对象

emplace_back

直接在容器尾部构造对象,避免拷贝/移动

高效插入对象到尾部

insert

先构造临时对象,再插入到指定位置

在指定位置插入现有对象

emplace

直接在指定位置构造对象,避免拷贝/移动

在指定位置高效插入新对象


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

3.STL的变化

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

以下介绍几个容器:

1. std::array

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

2.std::forward_list

  • 特点:单向链表(比 std::list 更轻量)。
  • 优势:内存占用更小,适合简单链表操作。
  • 示例:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 功能)。
  • 优势:适合存储和返回多类型组合数据。
  • 示例:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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. 对于自定义类型的成员,需要看这个成员有没有实现移动构造函数(移动赋值函数),
    • 如果有则调用该成员的移动构造函数(移动赋值函数)。
    • 如果没有就调用拷贝构造函数(赋值重载重载)。

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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();
}

3.拷贝与移动的区别

特性

拷贝构造/赋值

移动构造/赋值

操作方式

复制资源(通常深拷贝)

转移资源的所有权

参数类型

const T&(左值引用)

T&&(右值引用)

性能

较慢(需要额外资源分配)

较快(资源直接转移)


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

defaultdelete

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyClass {
public:
    MyClass() = default;  // 使用默认构造函数
    MyClass(const MyClass&) = default;  // 使用默认拷贝构造函数
};

2.删除函数(=delete 可以显式禁用默认成员函数,这样编译器就不会生成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyClass {
public:
    MyClass() = default;
    MyClass(const MyClass&) = delete;  // 禁止拷贝构造
};

final 和override

1.final 用于禁止类被继承或者重写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Base {
public:
    virtual void func() final {}  // 禁止进一步重写
};

class Derived : public Base {
    // void func() override {}  // 编译错误
};

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Base {
public:
    virtual void func() {}
};

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

5. lambda 表达式

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

基本语法

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

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

示例1:打印 hello world

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	int main()
{
	auto hello = []()->void {
		cout << "hello world" << endl;
		};

	hello();
	return 0;
}
  • 捕获列表为空,表示不捕获任何变量。
  • lambda表达式 无参数且无返回值,执行打印 hello world 的操作。

示例2:add 函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 是一个类模板,语法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <class Ret, class... Args>
class function<Ret(Args...)>;

2.function 的功能

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

3.使用示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)> mumultiplyfunc = [](int x, int y) {
		return x * y;
		};
	cout << mumultiplyfunc(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 在一些场景中,能够大幅简化代码,使得代码的可读性更高。就比如解决下面这道算法题: 逆波兰表达式求值 - 力扣(LeetCode) 比较传统的写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 的写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 中的一个工具(函数模板),作用是将函数和参数绑定,生成一个新的可调用对象(函数对象),这个对象可以像普通函数一样调用。

语法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <functional>

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

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

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

使用示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 表达式。

拜拜,下期再见😏

摸鱼ing😴✨🎞

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【深度剖析 C++11】 第三弹:C++11完结,迈进高效编程的新纪元
之前我们学过的类模板以及函数模板的参数都是不可变参数模板,模板定义了几个参数,实例化就需要传递几个参数。
换一颗红豆
2024/12/20
1260
【深度剖析 C++11】 第三弹:C++11完结,迈进高效编程的新纪元
C++11特性大杂烩
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。
梨_萍
2023/05/11
9660
C++11特性大杂烩
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
c++11 标准的发布为 c++ 带来了革命性的变化,引入了许多强大的新特性,使代码更简洁、高效且现代化。这些特性不仅提升了开发效率,还优化了性能,是现代 c++ 编程的重要基石。本篇文章,我们将重点探讨 c++11 的几个核心改进:列表初始化、右值引用和移动语义、类的新默认成员函数以及lambda表达式。
ephemerals__
2025/04/10
1580
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
【c++11】c++11新特性(下)(可变参数模板、default和delete、容器新设定、包装器)
之前我们学习了c++11的部分新特性:列表初始化、右值引用、类的新默认成员函数和lambda表达式等:
ephemerals__
2025/04/26
530
【c++11】c++11新特性(下)(可变参数模板、default和delete、容器新设定、包装器)
【C++11】lambda和包装器
原来C++类中,有6个默认成员函数:构造函数/析构函数/拷⻉构造函数/拷⻉赋值重载/取地址重 载/const 取地址重载,最后重要的是前4个,后两个⽤处不⼤,默认成员函数就是我们不写编译器 会⽣成⼀个默认的。C++11 新增了两个默认成员函数,移动构造函数和移动赋值运算符重载。
用户11375356
2025/02/11
1500
【C++11】lambda和包装器
【C++】————C++11
1998年是C++标准委员会成立的第一年,本来计划以后每5年视实际需要更新一次标准,C++国际标准委员会在研究C++ 03的下一个版本的时候,一开始计划是2007年发布,所以最初这个标准叫C++07。但是到06年的时候,官方觉得2007年肯定完不成C++ 07,而且官方觉得2008年可能也完不成。最后干脆叫C++0x。x的意思是不知道到底能在07还是08还是09年完成。结果2010年的时候也没完成,最后在2011年终于完成了C++标准。所以最终定名为C++11。
用户11036582
2024/08/16
1180
【C++】————C++11
【C++】深入剖析C++11新特性
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习。C++11增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以本期博客主要讲解实际中比较实用的语法。
青衫哥
2023/10/17
7440
【C++】深入剖析C++11新特性
【C++进阶】C++11的认识与学习
在C++11中,新增加了列表初始化,即可以用(=){},给所有的内置类型和自定义类型初始化(等号可有可无)。
aosei
2024/01/23
2060
【C++进阶】C++11的认识与学习
【c++】一篇文章带你了解c++11的新特性&&c++11详解
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。
用户10925563
2024/08/06
2590
【c++】一篇文章带你了解c++11的新特性&&c++11详解
C++ —— 剑斩旧我 破茧成蝶—C++11
1. C++11以后想统⼀初始化⽅式,试图实现⼀切对象皆可⽤{}初始化,{}初始化也叫做列表初始化
迷迭所归处
2024/11/20
1180
C++ —— 剑斩旧我 破茧成蝶—C++11
【C++】C++11常用特性总结
1. 以前在C语言的时候,{}一般用于初始化数组或结构体,例如下面代码的初始化方式,数组array1和array2可以在创建的同时进行初始化,同样结构体p1和p2也可以在定义的时候初始化,p2的_y成员变量默认初始化为0.
举杯邀明月
2023/05/03
8690
【C++】C++11常用特性总结
C++11常用的一部分新特性
C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自 定义的类型,使用初始化列表时,可添加等号(=),也可不添加。
有礼貌的灰绅士
2023/06/14
4800
C++11常用的一部分新特性
C++11新特性 右值引用与新的类功能
在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习。C++11增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以本节主要讲解实际中比较实用的语法。
用户11317877
2024/10/16
1650
C++11新特性 右值引用与新的类功能
C++11(下篇)
比较重要的是前4个,后两个的用处并不大,默认的成员函数就是我们不写编译器会生成一个默认的。
芝士就是菜
2023/04/20
6780
C++11(下篇)
C++11
相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中 约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个 重点去学习。
小灵蛇
2024/06/06
1850
C++11
C++11(3)
C++11 的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含 固定数量 的模版参数,可变模版参数无疑是一个巨大的改
啊QQQQQ
2024/11/19
1240
C++11(3)
【C++11】可变参数模板/新的类功能/lambda/包装器--C++
成员变量声明时给缺省值是给初始化列表用的,如果没有显示在初始化列表初始化,就会在初始化列表用这个却绳子初始化,这个我们在类和对象部分讲过了,点击跳转,可以查看我的主页哦.
小志biubiu
2025/02/27
1720
【C++11】可变参数模板/新的类功能/lambda/包装器--C++
【C++11】解锁C++11新纪元:深入探索Lambda表达式的奥秘
前言:在C++编程语言的悠久历史中,每一次标准的更新都带来了革命性的变化,推动了编程范式和性能优化的新边界。C++11标准,作为这一漫长演进过程中的一个重要里程碑,不仅巩固了C++作为高性能系统级编程语言的地位,还引入了众多现代编程特性,极大地丰富了C++的表达力和易用性。其中,lambda表达式和std::function无疑是这些新特性中最引人注目且影响深远的两个
Eternity._
2024/08/05
1470
【C++11】解锁C++11新纪元:深入探索Lambda表达式的奥秘
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
但是到了c++11实现了可以用{}对容器进行一些初始化等,比如push/inset多参数构造的对象时,{}初始化会很⽅便,这是因为每个类型它都会有个initializer_list的一个构造,这样就方便了我们操作。
羑悻的小杀马特.
2025/01/23
550
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
【C++11(中)】—— 我与C++的不解之缘(三十一)
但是这样未必有些太麻烦了,如果我们还要传递4、5、6个甚至更多参数的,那还要一个个去实现。
星辰与你
2025/04/05
890
【C++11(中)】—— 我与C++的不解之缘(三十一)
相关推荐
【深度剖析 C++11】 第三弹:C++11完结,迈进高效编程的新纪元
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验