探索C++14新特性:更强大、更高效的编程

简介: 探索C++14新特性:更强大、更高效的编程

c++14并没有太大的改动,就连官方说明中也指出,c++14相对于c++11来说是一个比较小的改动,但是在很大程度上完善了c++11,所以可以说c++14就是在c++11标准上的查漏补缺。

image.png

C++14在2014年8月18日正式批准宣布,同年12月15日正式发布release版本。本文中将就变动部分做一个总结,有需要改进和提升的地方希望大家批评指正。


一、C++14新特性


1.1新的语言特性

  • 变量模板
  • 泛型 lambda
  • lambda 初始化捕获
  • 新建/删除省略
  • 放宽对 constexpr 函数的限制
  • 二进制文字
  • 数字分隔符
  • 函数的返回类型推导
  • 具有默认非静态成员初始值设定项的 聚合类。


1.2新库功能

  • std::make_unique
  • std::shared_timed_mutexstd::shared_lock
  • std::整数序列
  • 标准::交换
  • std::引用
  • 以及对现有图书馆设施的许多小改进,例如
  • 某些算法的两范围重载
  • 类型特征的类型别名版本
  • 用户定义的basic_string持续时间复杂的文字
  • ETC。


1.3变量模板


C++11及之前,我们只有针对类和函数的模板。C++14中,新增了变量模板:

template<class T>
constexpr T pi = T(3.1415926535897932385L);
template<class T>
T circular_area(T r)
{
  return pi<T> *r * r;
}

变量模板同样可以在类变量中使用:

template<class T>
class X {
  static T s;
};
template<class T>
T X<T>::s = 0;

类似函数和类模板,当变量模板被引用时,则会发生实例化。


1.4lambda 表达式的新增功能


1)泛化


支持在 lambda 表达式中使用 auto 定义变量类型:

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
  auto glambda = [](auto& a) { cout << a << " "; };
  int a[] = { 4, 2, 6, 3, 7, 5 };
  for_each(a, a + sizeof(a) / sizeof(int), glambda);
  cout << endl;
}

2)对捕获的变量和引用进行初始化

include <iostream>
using namespace std;
int main()
{
  int x = 4;
  auto y = [&r = x, x = x + 1]()->int
  {
    r += 2;
    return x * x;
  }(); 
  cout << "x = " << x << " y = " << y << endl;
}

640.png

1.5constexpr 函数可以包含多个语句

在C++11中,如果想使用constexpr方法,只能包含一个返回语句。C++14中,放宽了此要求,允许constexpr函数中声明变量,使用循环和条件语句等:

#include <iostream>
#include <cmath>
using namespace std;
constexpr bool isPrimitive(int number)
{
  if (number <= 0)
  {
    return false;
  }
  for (int i = 2; i <= sqrt(number) + 1; ++i)
  {
    if (number % i == 0)
    {
      return false;
    }
  }
  return true;
}
int main()
{
  cout << boolalpha << isPrimitive(102) << " " << isPrimitive(103);
  return 0;
}


在C++11中,我们一般需要通过递归来实现相同的功能:

constexpr bool isPrimitive(int number, int currentFactor, int maxFactor)
{
  return currentFactor == maxFactor ? true : 
      (number % currentFactor == 0 ? false : 
        isPrimitive(number, currentFactor + 1, maxFactor));
}
constexpr bool isPrimitive(int number)
{
  return number <= 0 ? false : isPrimitive(number, 2, sqrt(number) + 1);
}


1.6整型字面量


1)二进制字面量


支持使用 0b 开头的一串数字作为二进制表示的整型:

int a = 0b10101001110; // 1358


2)数字分割符


支持在数字中使用单引号进行分割(便于阅读)。在编译时,这些单引号会被忽略。

int a = 123'456'789; // 123456789


1.7返回类型自动推导


在C++14中,我们可以使用 auto 作为函数返回值并且不需要指明其返回类型的推导表达式

int x = 1;
auto f() { return x; }
/* c++11
auto f() -> decltype(x) { return x; } 
*/

这种类型推导有一些限制:

  • 一个函数中所有返回字句必须推导出相同的类型;
  • 使用 {} 包裹的数据作为返回值时,无法推导其类型;
  • 虚函数coroutine 不能被推导;
  • 函数模板中可以使用类型推导,但是其显式实例化和特化版本必须使用相同的返回类型描述符。


1.8exchange


exchange 用于移动语义,可以使用指定的新值替换掉原值,并返回原值。其定义在C++20中被简单修改如下:

template<class T, class U = T>
constexpr // since C++20
T exchange(T& obj, U&& new_value)
{
    T old_value = std::move(obj);
    obj = std::forward<U>(new_value);
    return old_value;
}


其使用如下:

#include <iostream>
#include <vector>
#include <utility>
using namespace std;
int main()
{
  vector<int> v = {5, 6, 7};
  std::exchange(v, { 1,2,3,4 });
  std::copy(begin(v), end(v), ostream_iterator<int>(cout, " "));
  cout << endl;
}


1.9quoted


该类用于字符串转义的处理。使用 out << quoted(s, delim, escape) 的形式,可以将字符串 s 的转义格式写入输出流中;使用 in >> quoted(s, delim, escape) 可以将输入流去除转义格式后写入字符串 s 中。其中,delim 指明了需要转义的字符,escape 指明了修饰该转移字符的字符:

#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
int main()
{
  stringstream ss;
  string in = "String with spaces, and embedded \"quotes\" too";
  string out;
  auto show = [&](const auto& what) 
  {
    &what == &in
      ? cout << "read in     [" << in << "]\n"
      << "stored as   [" << ss.str() << "]\n"
      : cout << "written out [" << out << "]\n\n";
  };
  ss << quoted(in); 
  show(in);
  ss >> quoted(out);
  show(out);
  ss.str(""); 
  in = "String with spaces, and embedded $quotes$ too";
  const char delim{ '$' };
  const char escape{ '%' };
  ss << quoted(in, delim, escape);
  show(in);
  ss >> quoted(out, delim, escape);
  show(out);
}

【文章福利】小编推荐自己的Linux C++技术交流群:【1106675687】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100名进群领取,额外赠送大厂面试题。


二、C++14经常考到的知识点


2.1C++14引入了哪些新特性?


C++14引入了一些新特性,包括但不限于以下内容:

  1. 通用Lambda表达式:允许在lambda函数中使用auto关键字来推导参数类型。
  2. 自动返回类型推导:允许使用auto关键字自动推导函数返回值类型。
  3. 初始化列表的泛型支持:可以使用auto关键字在初始化列表中推导元素类型。
  4. 带有二进制分隔符的整数字面量:可以在整数常量中使用单撇号作为分隔符,提高可读性。
  5. constexpr函数的扩展:constexpr函数可以包含更多操作,例如循环和条件判断。
  6. 变长参数模板(Variadic Templates)的改进:支持递归处理变长参数模板的展开。
  7. 返回void类型的lambda表达式:允许定义返回void类型的lambda函数。


2.2C++14中auto关键字的用法和限制是什么?

在C++14中,auto关键字用于自动类型推导,可以根据初始化表达式的类型来确定变量的类型。它的使用和限制如下:

  1. 自动类型推导:使用auto关键字声明变量时,编译器会根据初始化表达式的类型自动推导出变量的类型。
    auto x = 42; // 推导为int型 auto name = "John"; // 推导为const char*型
  2. 声明时必须初始化:使用auto声明变量时,必须进行初始化。因为编译器需要根据初始化表达式来推导出变量的类型。
    auto y; // 错误,未初始化
  3. 可与引用结合使用:auto关键字可以与引用一起使用,从而推导出引用的类型。
    int a = 10; auto& ref = a; // 推导为int&型,ref是a的引用
  4. 不支持数组或函数指针:auto不能直接用于数组或函数指针的声明。但可以通过decltype结合auto来实现对数组或函数指针类型进行推导。
    int arr[] = {1, 2, 3}; auto arrRef = arr; // 错误,无法推导arr的数组类型 decltype(arr) arrType; // 使用decltype获取arr的数组类型并声明arrType void foo(); auto funcPtr = foo; // 错误,无法推导foo的函数指针类型 decltype(foo)* funcPtrType; // 使用decltype获取foo的函数指针类型并声明funcPtrType

需要注意的是,auto在C++14中的用法和限制可能与之后的标准(如C++17、C++20等)有所不同,具体取决于编译器和所使用的标准版本。


2.3C++14中如何使用Lambda表达式?有什么改进?

在C++14中,使用Lambda表达式的语法与之前的C++版本相似。Lambda表达式是一种可以在代码中内联定义匿名函数的方式。


下面是一个使用Lambda表达式的示例:

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    // 使用Lambda表达式进行遍历打印
    std::for_each(numbers.begin(), numbers.end(), [](int num) {
        std::cout << num << " ";
    });
    return 0;
}


在Lambda表达式中,方括号 [] 用于捕获外部变量(可选)。小括号 ( ) 内指定参数列表(可选),箭头 -> 后面指定返回类型(可选)。


C++14对于Lambda表达式有一些改进,其中最显著的改进是可以自动推导返回类型。这意味着你不需要显式地指定返回类型,编译器会根据表达式体来推断返回类型。


以下是一个示例:

auto lambda = [](int a, int b) {
    return a + b;
};


在上述示例中,我们没有显式指定返回类型,但编译器会自动推断出返回类型为整数(因为a和b都是整数)。


此外,在C++14中还引入了泛型lambda,使得可以在lambda函数中使用auto关键字作为参数类型,更加灵活和方便。


2.4C++14对于constexpr关键字有何改进?


C++14对于constexpr关键字进行了一些改进,使得其更加灵活和强大。在C++11中,constexpr只能用于表示常量表达式的函数和构造函数,而在C++14中,它还可以用于一些额外的情况。


首先,在C++14中,constexpr函数可以包含一些非常量表达式的逻辑,只要这部分逻辑在运行时不会执行即可。这意味着我们可以在constexpr函数内使用循环、条件语句等非常量表达式的控制流程。


其次,C++14引入了对变量模板(Variable Templates)的支持,并且允许将变量声明为constexpr。这样我们就可以定义并初始化一个编译期间可计算的常量变量。

此外,在C++14中,对于某些标准库类型(如数组、字符串等),它们也提供了更多的支持以便于使用在编译期间计算出来的常量值。


2.5C++14中提供了哪些新的标准库组件和功能?


C++14引入了一些新的标准库组件和功能,以下是其中的一些主要特性:


  1. std::make_unique:提供了在堆上创建 unique_ptr 对象的便捷方式。
  2. std::integer_sequence:支持编译时整数序列的操作,用于元编程。
  3. std::user_defined_literals:允许用户定义自己的字面量后缀,扩展了语言的表达能力。
  4. 通用 lambda 表达式:允许使用 auto 参数声明参数类型,使得 lambda 表达式更加灵活。
  5. 变长模板参数折叠(Variadic template parameter packs expansion):可以将多个参数打包传递给模板函数或类,并且可以对它们进行展开操作。
  6. std::experimental 命名空间:引入了一些实验性质的标准库组件,如 optional、any、string_view 等。


2.6在C++14中,变长参数模板是如何使用的?


在C++14中,可以使用变长参数模板(Variadic Templates)来处理可变数量的函数参数。通过使用递归展开参数包的方式,可以灵活地处理任意数量的参数。


下面是一个示例:

#include <iostream>
// 递归终止条件:当没有剩余参数时停止递归
void printArgs() {
    std::cout << "All arguments have been printed." << std::endl;
}
// 可变参数模板:展开第一个参数并调用自身处理剩余参数
template<typename T, typename... Args>
void printArgs(T first, Args... args) {
    std::cout << "Argument: " << first << std::endl;
    printArgs(args...); // 递归调用自身处理剩余参数
}
int main() {
    printArgs(1, "Hello", 3.14, 'A');
    return 0;
}


输出结果:

Argument: 1
Argument: Hello
Argument: 3.14
Argument: A
All arguments have been printed.


在上述代码中,printArgs 是一个可变参数模板函数。它首先处理第一个传入的参数 first,然后递归地调用自身处理剩余的 args 参数。当所有参数都被展开并打印完毕后,最终会到达递归终止条件。


这种方式使得我们能够在编译时处理不同数量和类型的函数参数,并且可以灵活地进行操作。


2.7在C++14中,是否允许在lambda函数内定义其他函数或类?


在C++14中,lambda函数内是不允许定义其他函数或类的。Lambda函数是一个匿名的函数对象,它通常用于简化代码,提供一种在局部范围内编写小型函数的方式。Lambda函数本质上是一个闭包,它可以捕获外部作用域中的变量,并且具有与普通函数相似的行为。


然而,在C++17中引入了嵌套lambda的概念,使得在lambda函数内定义其他lambda函数成为可能。在这种情况下,内层的lambda函数可以访问外层lambda函数的变量。所以如果你想要在C++14中定义其他函数或类,建议将其定义在lambda之外的范围内。

2.8C++14是否支持原始字符串字面量(raw string literals)?如何使用它们?


是的,C++14支持原始字符串字面量(raw string literals)。


原始字符串字面量可以用来表示包含特殊字符(例如转义序列和引号)的字符串,而无需使用转义符号。它们由R"delim(raw_characters)delim"的语法表示,其中delim可以是任何非空字符序列,并且在开始和结束位置上必须匹配。


以下是一个示例:

#include <iostream>
int main() {
    const char* str1 = R"(Hello \n World!)";
    std::cout << str1 << std::endl;  // 输出:Hello \n World!
    const char* str2 = R"###(This is a "quoted" string.)###";
    std::cout << str2 << std::endl;  // 输出:This is a "quoted" string.
    return 0;
}


在上面的示例中,我们使用了原始字符串字面量来创建包含特殊字符的字符串,而不需要使用额外的转义符号。


2.9在C++14中,std::make_unique和std::make_shared这两个函数的作用是什么?


在C++14中,std::make_uniquestd::make_shared是用于创建智能指针的函数模板。

  • std::make_unique:用于创建一个std::unique_ptr对象,它拥有独占所有权的动态分配对象。这个函数接受参数并返回一个std::unique_ptr,它会自动管理内存释放。示例:
auto ptr = std::make_unique<int>(42);
  • std::make_shared:用于创建一个std::shared_ptr对象,它可以被多个指针共享的动态分配对象。这个函数接受参数并返回一个std::shared_ptr,它使用引用计数来管理内存释放。示例:
auto ptr = std::make_shared<int>(42);

这两个函数可以减少手动进行资源管理的工作量,并提供了更安全、更简洁的方式来处理动态分配对象。


2.10C++14引入了统一初始化语法(uniform initialization syntax),具体有哪些变化?


C++14引入了统一初始化语法(uniform initialization syntax),它允许使用一种更统一和一致的方式进行初始化。具体的变化包括以下几个方面:

  1. 初始化列表(initializer list):可以使用花括号 {} 来初始化对象,无论是简单类型还是复杂类型。例如:
    int num{ 42 }; std::vector vec{ 1, 2, 3 };
  2. 自动类型推导:在使用统一初始化语法时,编译器可以自动推导出变量的类型。
    auto value{ 3.14 }; // 推导为 double 类型 auto str{ "Hello" }; // 推导为 const char[6] 类型
  3. 统一构造函数调用语法:通过统一初始化语法,可以直接调用类的构造函数进行对象的创建。
    class MyClass { public: MyClass(int value) { /* 构造函数实现 */ } // ... }; MyClass obj{ 42 }; // 调用构造函数创建对象
  4. 空初始化:可以使用 {}() 进行空初始化,不再需要显式地指定默认值。
    int num{}; // 初始化为0 std::string str{}; // 初始化为空字符串

这些变化使得初始化更加灵活和一致,并且提供了更强大的类型推导能力。注意,在使用统一初始化语法时,要注意类型的精确匹配和可能的隐式转换。


三、C++14 新特性总结


C++14 这一继 C++11 之后的新的 C++ 标准已经被正式批准,正在向ISO 提交,将于年内发布。 C++ 之父 Bjarne Stroustrup 说道,尽管与 C++11 相比,C++14 的改进“有意做的比较小”,但是仍然为用户“带来了极大的方便”,是实现使C++“对新手更为友好”这一目标的步骤之一

在C++ 的时间表中, C++14 按计划是一个小版本,完成制定 C++11 标准的剩余工作,目的是使 C++ 成为一门更清晰、更简单和更快速的语言。新的语言特性留到了未来的 C++17 标准中。

640.jpg


C++14 的主要特性可以分为三个领域:Lambda 函数、constexpr 和类型推导。


3.1Lambda 函数

C++14 的泛型 Lambda 使编写如下语句成为可能:

auto lambda = [](auto x, auto y) {return x + y;};

而另一方面,C++11 要求 Lambda 参数使用具体的类型声明,比如:

auto lambda = [](int x, int y) {return x + y;};

此外,新标准中的 std::move 函数可用于捕获 Lambda 表达式中的变量,这是通过移动对象而非复制或引用对象实现的:

std::unique_ptr ptr(new int(10));
auto lambda = [value = std::move(ptr)] {return *value;};


(1)lambda参数auto

在c++11中,lambda表达式参数需要使用具体的类型声明。

auto f = [] (int a) { return a; }

在c++14中,lambda表达式参数可以直接为auto。

auto f = [] (auto a) { return a; };
cout << f(1) << endl;
cout << f(2.3f) << endl;


3.2constexpr

在 C++11 中,使用 constexpr 声明的函数可以在编译时执行,生成一个值,用在需要常量表达式的地方,比如作为初始化模板的整形参数。C++11 的 constexpr 函数只能包含一个表达式,C++14 放松了这些限制,支持诸如 if 和 switch 等条件语句,支持循环,其中包括基于区间(range)的 for 循环。


(1)变量模板

c++14支持变量模板。

template<class T>
constexpr T pi = T(3.1415926535897932385L);
int main() {
    cout << pi<int> << endl; // 3
    cout << pi<double> << endl; // 3.14159
    return 0;
}


(2)别名模板

c++14支持别名模板。

template<typename T, typename U>
struct A {
    T t;
    U u;
};
template<typename T>
using B = A<T, int>;
int main() {
    B<double> b;
    b.t = 10;
    b.u = 20;
    cout << b.t << endl;
    cout << b.u << endl;
    return 0;
}


(3)constexpr的限制

c++14相较于c++11减少了限制:c++11和c++14中constexpr函数均可以使用递归。

constexpr int factorial(int n) { // C++14 和 C++11均可
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

c++14还可以使用局部变量和循环。

constexpr int factorial(int n) { // C++11中不可,C++14中可以
    int ret = 0;
    for (int i = 0; i < n; ++i) {
        ret += i;
    }
    return ret;
}

c++11中constexpr函数中必须把所有东西放在一个单独的return语句中。

constexpr int func(bool flag) { // C++14 和 C++11均可
    return 0;
}

c++14中constexpr函数没有上述限制。

constexpr int func(bool flag) { // C++11中不可,C++14中可以
    if (flag) return 1;
    else return 0;
}


3.3类型推导

C++11 仅支持 Lambda 函数的类型推导,C++14 对其加以扩展,支持所有函数的返回类型推导:

auto DeducedReturnTypeFunction();


因为 C++14 是强类型语言,有些限制需要考虑:

  • 如果一个函数的实现中有多个返回语句,这些语句一定要推导出同样的类型。
  • 返回类型推导可以用在前向声明中,但是在使用它们之前,翻译单元中必须能够得到函数定义。
  • 返回类型推导可以用在递归函数中,但是递归调用必须以至少一个返回语句作为先导,以便编译器推导出返回类型。


C++14 带来的另一个类型推导方面的改进是 decltype(auto) 语法,它支持使用与 auto 同样的机制计算给定表达式的类型。auto 和 decltype 在 C++11 中就已经出现了,但是它们在推导类型时使用了不同的机制,这可能会产生不同的结果。


C++14 中的其他改变包括可以声明变量模板,支持使用 0b 或 0B 前缀来声明二进制字面常量。InfoQ 已经介绍过 C++14 中可能破坏 C++11 程序的其他小型修改


主流 C++ 编译器对新语言特性的支持正在有条不紊地开发: Clang “完全实现了当前草案的所有内容”; GCC Visual Studio 也对 C++14 的新特性提供了一些支持。


(1)函数返回值类型推导

c++14对函数返回类型推导规则做了优化:

auto func(int i) {  //C++11编译非法,c++14支持auto返回值类型推导
    return i;
}
int main() {
    cout << func(4) << endl;
    return 0;
}

支持函数模块返回值类型推导:

template<typename T>
auto func(T t) { return t; }
int main() {
    cout << func(4) << endl;
    cout << func(3.4) << endl;
    return 0;
}

auto返回值用例:

// 编译失败,多个return语句必须返回相同类型。
auto func(bool flag) {
    if (flag) return 1;
    else return 2.3;
}
// 编译失败,不能返回初始化列表
auto func1() {
    return {1, 2, 3};
}
//虚函数不能返回类型推导
class A{
    virtual auto func() { return 1; }
};
//返回值类型推导可以提前前声明,但使用前必须进行函数定义。
auto f();               // declared, not yet defined
auto f() { return 42; } // defined, return type is int
// 回类型推导可以用在递归函数中,但是递归调用必须以至少一个返回语句作为先导,以便编译器推导出返回类型。
auto sum(int i) {
    if (i == 1)
        return i;              // return int
    else
        return sum(i - 1) + i; // ok
}
int main() {
    cout << f() << endl;
    return 0;
}


3.4C++14其他


(1)[[deprecated]]标记

c++14中增加deprecated标记,修饰类、变量、函数等。编译时产生警告,提醒用户该标记修饰的内容未来可能会被丢弃。

struct [[deprecated]] A { };
int main() {
    A a;
    return 0;
}

(2)二进制字面量与字面量分隔符

c++14引入了二进制字面量和字面量分隔符。

int a = 0b0001'0011'1010;
double b = 3.14'1234'1234'1234;

(3)std::make_unique

c++11中有std::make_shared,c++14增加了std::make_unique。

struct A {};
std::unique_ptr<A> ptr = std::make_unique<A>();

(4)std::shared_timed_mutex与std::shared_lock

c++14通过std::shared_timed_mutex和std::shared_lock来实现读写锁,保证多个线程可以同时读,但是写线程必须独立运行,写操作和读操作不可同时进行,这种情况下才能从shared_mutex中获取性能优势。


c++11 中互斥量

640.jpg

c++14互斥量管理类-锁

  • shared_lock是read lock。搭配std::shared_mutex使用,被锁定后允许其它线程执行同样被shared_lock的代码。
  • lock_gurd和unique_lock是write lock。被锁定后,不允许其它线程执行被share_lock或unique_lock的代码。


通常这样定义:

typedef std::shared_lock<std::shared_mutex> ReadLock;
typedef std::lock_guard<std::shared_mutex> WriteLock;


实现方式:

struct ThreadSafe {
    mutable std::shared_timed_mutex mutex_;
    int value_;
    ThreadSafe() {
        value_ = 0;
    }
    int get() const {
        std::shared_lock<std::shared_timed_mutex> lock(mutex_);
        return value_;
    }
    void increase() {
        std::unique_lock<std::shared_timed_mutex> lock(mutex_);
        value_ += 1;
    }
};


(5)std::integer_sequence

表示一个编译时的整型序列。


(6)std::exchange

以 new_value 替换 obj 的值,并返回 obj 的旧值。注意与std::swap的区别。

vector<int> v{4,5,6,7};
vector<int> x = std::exchange(v, {1,2,3,4});
cout << v.size() << endl;
for (int a : v) {
       cout << a << " ";
}
cout<<endl;
for (int a : x) {
      cout << a << " ";
}

(7)std::quoted

c++14引入std::quoted用于给字符串添加双引号。

string str = "hello world";
cout << str << endl;
cout << std::quoted(str) << endl;
/* 输出
* hello world
* "hello world"
*/


精品文章推荐阅读:

相关文章
|
11天前
|
编译器 Linux C语言
C++新特性“CPU优化对齐”
C++新特性“CPU优化对齐”
29 3
|
11天前
|
编译器 API C++
c++ 新特性 概念和约束 “无规矩 难成方圆”
c++ 新特性 概念和约束 “无规矩 难成方圆”
13 1
|
4天前
|
存储 编译器 程序员
近4w字吐血整理!只要你认真看完【C++编程核心知识】分分钟吊打面试官(包含:内存、函数、引用、类与对象、文件操作)
近4w字吐血整理!只要你认真看完【C++编程核心知识】分分钟吊打面试官(包含:内存、函数、引用、类与对象、文件操作)
|
4天前
|
C++
C++核心编程三:函数提高(持续更新)
C++核心编程三:函数提高(持续更新)
|
4天前
|
编译器 C++
C++核心编程二:引用(持续更新)
C++核心编程二:引用(持续更新)
|
4天前
|
程序员 编译器 C++
C++核心编程一:内存分区模型(持续更新)
C++核心编程一:内存分区模型(持续更新)
|
11天前
|
存储 编译器 C++
C++新特性 扩展和聚合类型
C++新特性 扩展和聚合类型
12 3
|
11天前
|
存储 算法 编译器
C++ 新特性 lamada表达式
C++ 新特性 lamada表达式
12 1
|
11天前
|
存储 Linux API
C++新特性 线程局部存储
C++新特性 线程局部存储
11 0
|
11天前
|
算法 编译器 C++
C++新特性 右值引用&&
C++新特性 右值引用&&
17 2

热门文章

最新文章

相关产品

  • 云迁移中心