当前位置: 首页 > news >正文

做图书馆网站模板网店运营工作内容

做图书馆网站模板,网店运营工作内容,游戏网站制作模板,网络营销与网络推广的异同导论 c17新特性引入了许多新的语法,这些语法特性更加清晰,不像传统语法,语义飘忽不定,比如‘a’你根本不知道是宽字符还是UTF-8 字符。以及测试i i,最后结果到底是多少。这种问题很大情况是根据编译器的优化进行猜测&a…

导论

        c17新特性引入了许多新的语法,这些语法特性更加清晰,不像传统语法,语义飘忽不定,比如‘a’你根本不知道是宽字符还是UTF-8 字符。以及测试i++ ++i,最后结果到底是多少。这种问题很大情况是根据编译器的优化进行猜测,不同环境,得出不同结果。而c17对这些问题给出完美的解决方案!

字符字面量

理论

官方给出的语法:

  • 普通字符字面量: 'c-char'

  • UTF-8 字符字面量: u8'c-char'

  • UTF-16 字符字面量: u'c-char'

  • UTF-32 字符字面量: U'c-char'

  • 宽字符字面量: L'c-char'

  • 普通多字符字面量: 'c-char-sequence'

  • 宽字符多字符字面量: L'c-char-sequence'

不太懂??基础薄弱!!

  1. 普通字符字面量:

    • 形式: 'c-char'
    • 表示: 一个单个的普通字符字面量,通常为 8 位 ASCII 字符。
    • 类型: char
  2. UTF-8 字符字面量:

    • 形式: u8'c-char'
    • 表示: 一个单个的 UTF-8 编码的字符字面量。
    • 类型: char8_t (C++20 引入)
  3. UTF-16 字符字面量:

    • 形式: u'c-char'
    • 表示: 一个单个的 UTF-16 编码的字符字面量。
    • 类型: char16_t
  4. UTF-32 字符字面量:

    • 形式: U'c-char'
    • 表示: 一个单个的 UTF-32 编码的字符字面量。
    • 类型: char32_t
  5. 宽字符字面量:

    • 形式: L'c-char'
    • 表示: 一个单个的宽字符字面量。宽字符的大小由实现定义,通常为 16 位或 32 位。
    • 类型: wchar_t
  6. 普通多字符字面量:

    • 形式: 'c-char-sequence'
    • 表示: 一个字符序列,由多个普通字符组成。
    • 类型: 数组类型 char[N],其中 N 为字符序列的长度。
  7. 宽字符多字符字面量:

    • 形式: L'c-char-sequence'
    • 表示: 一个字符序列,由多个宽字符组成。
    • 类型: 数组类型 wchar_t[N],其中 N 为字符序列的长度。

这些不同类型的字符字面量主要有以下区别:

  1. 字符编码:

    • 普通字符为 8 位 ASCII 编码。
    • UTF-8、UTF-16 和 UTF-32 字符分别采用 UTF-8、UTF-16 和 UTF-32 编码。
    • 宽字符的编码由实现定义,通常为 16 位或 32 位。
  2. 表示范围:

    • UTF-8、UTF-16 和 UTF-32 字符可以表示更广泛的字符集,包括非 ASCII 字符。
    • 宽字符的表示范围由实现定义。
  3. 内存占用:

    • 普通字符和 UTF-8 字符占用 1 个字节。
    • UTF-16 字符占用 2 个字节。
    • UTF-32 字符和宽字符占用 4 个字节。

        选择合适的字符类型取决于您的具体需求。对于仅需要处理 ASCII 字符的场景,使用普通字符就足够了。如果需要支持更广泛的字符集,可以考虑使用 UTF-8、UTF-16 或 UTF-32 字符。如果需要与遗留代码兼容,或者需要处理宽字符的场景,则可以使用宽字符。 现在我们可以定义出适合的字符串类型,写出最佳的程序。

实践

普通字符字面量:
char c1 = 'a';
char c2 = '\n';
char c3 = '\x2a'; // 等同于 '*'UTF-8 字符字面量:
char8_t c1 = u8'a';
// char8_t c2 = u8'¢'; // 错误,¢无法用单个UTF-8码元表示
// char8_t c3 = u8'猫'; // 错误,猫无法用单个UTF-8码元表示
// char8_t c4 = u8'🍌'; // 错误,🍌无法用单个UTF-8码元表示UTF-16 字符字面量:
char16_t c1 = u'a';
char16_t c2 = u'¢';
char16_t c3 = u'猫';
// char16_t c4 = u'🍌'; // 错误,🍌无法用单个UTF-16码元表示UTF-32 字符字面量:
char32_t c1 = U'a';
char32_t c2 = U'¢';
char32_t c3 = U'猫';
char32_t c4 = U'🍌';宽字符字面量:
wchar_t wc1 = L'a';
wchar_t wc2 = L'¢';
wchar_t wc3 = L'猫';
wchar_t wc4 = L'🍌'; // 在Windows上,这可能是非法的普通多字符字面量:
int mc1 = 'ab'; // 实现定义的值
int mc2 = 'abc'; // 实现定义的值宽字符多字符字面量:
wchar_t wmc1 = L'ab'; // 实现定义的值

有关变量的新语法

变量的评估顺序

表达式的求值顺序:

  • C++ 标准没有规定表达式中各个子表达式的求值顺序,除了一些特定的情况。

  • 通常编译器可以自由选择求值顺序,只要最终结果与按照左到右的顺序求值一致。

        x = (++x, ++y); 传统cpp并没有标准的定义到底谁先执行,都是由编译器优化,这就会造成环境不同,效果不同,争的你死我活。现在c17是这样解决的。

C++ 标准库中的 std::evaluatestd::as_const 这两个工具函数:

  1. std::evaluate (C++23):

    • 功能: 强制求值一个表达式,确保其副作用按照预期顺序发生。

    • 声明: template<class T> constexpr T&& evaluate(T&& t) noexcept;

    • 使用:

      int x = 0, y = 0;
      x = (++x, ++y); // 存在顺序未定义,可能 x 或 y 先增加
      x = std::evaluate((++x, ++y)); // 确保 x 和 y 按从左到右的顺序增加
    • 作用: 帮助开发者明确表达式的求值顺序,避免由于未定义行为导致的bug。

  2. std::as_const (C++17):

    • 功能: 获取一个表达式的常量引用,避免意外修改。

    • 声明: template<class T> constexpr const T& as_const(T& t) noexcept;

    • 使用:

      std::string s = "hello";
      std::string_view sv = s; // 可能意外修改 s
      std::string_view sv = std::as_const(s); // 确保 sv 只能读取 s 的内容
    • 作用: 帮助开发者强制使用只读引用,防止无意中修改原对象。

        总之, std::evaluatestd::as_const 是 C++ 标准库提供的两个有用的工具函数,前者解决表达式求值顺序的问题,后者解决引用可能被意外修改的问题。开发者可以在需要时使用它们来编写更加健壮的代码。

ifswitch初始化

这种多说无益,直接看示例就明白了。

auto lambda = [](int x) {if (int y = x * x; y > 100) {return y;} else {return 0;}
};int result = lambda(11); // result 为 121auto lambda = [](char c) {switch (int x = c; x) {case 'a':return 1;case 'b':return 2;default:return 0;}
};int result = lambda('b'); // result 为 2

 结构化绑定声明 简化代码。

可以看我往期文章,在此简单举个例子

#include <iostream>
#include <tuple>int main() {std::tuple<int, char, std::string> t{42, 'a', "hello"};//变量的数量必须与复合类型的元素数量一致。auto [x, y, z] = t;std::cout << x << ", " << y << ", " << z << '\n'; // 输出: 42, a, helloreturn 0;
}

左值引用和右值引用

可以看我往期文章,就不再赘述,这是重中之重。

constexpr consteval 编译时求值

constexpr 和 consteval 是 C++11 和 C++20 引入的两个关键字,它们都用于在编译时执行计算,但是它们之间有一些区别:

  1. constexpr:

    • constexpr 表示该变量或函数在编译时就可以计算出它的值。
    • constexpr 函数可以在编译时执行,也可以在运行时执行。
    • 如果 constexpr 函数在编译时无法计算出结果,编译器会尝试在运行时执行该函数。
    • constexpr 可以用于变量、函数和类的成员函数。
  2. consteval:

    • consteval 是 C++20 引入的,它比 constexpr 更加严格。
    • consteval 函数必须在编译时就能计算出结果,不能在运行时执行。
    • 如果 consteval 函数在编译时无法计算出结果,编译器会报错。
    • consteval 只能用于函数,不能用于变量或类的成员函数。

举例

constexpr 变量
constexpr int x = 42;
constexpr std::array<int, 3> arr = {1, 2, 3};constexpr 构造函数
struct Point {constexpr Point(int x, int y) : x(x), y(y) {}int x, y;
};
constexpr Point p(1, 2); // 在编译时创建 p 对象consteval关键字
consteval int square(int x) {return x * x;
}
constexpr int y = square(3); // 在编译时计算出 y = 9

总的来说:

  • constexpr 是一种"可能在编译时计算"的函数或变量,而 consteval 是一种"必须在编译时计算"的函数。
  • constexpr 提供了更大的灵活性,但 consteval 提供了更严格的编译时计算保证。
  • 开发者应该根据具体需求选择使用 constexpr 还是 consteval如果一个函数在编译时就能计算出结果,使用 consteval 更合适;如果需要在运行时也能正常执行,使用 constexpr 更合适。

任意类型变量 any variant

variant 编译期

std::variant 是 C++17 引入的一个非常有用的类型,它可以表示一个在多个类型之间进行选择的值。它提供了一种安全和高效的方式来处理可能出现的多种类型。

以下是 std::variant 的一些主要特点:

  1. 可以包含多种类型: std::variant 可以存储不同类型的值,这些类型由开发者在定义 std::variant 时指定。

  2. 类型安全: 与使用 void* 或者联合(union)相比, std::variant 提供了更好的类型安全性。它可以在编译时就检查访问是否合法,从而避免运行时错误。

  3. 访问安全: std::variant 提供了多种安全的访问方式,如 std::getstd::visit 等,可以确保在访问时不会出现未定义行为。

  4. 无需手动内存管理: std::variant 会自动管理其包含的值的生命周期,开发者不需要手动分配或释放内存。

any  运行期

std::any 是 C++17 引入的一个很有用的类型,它可以用来存储和传递任意类型的值。它提供了一个安全和高效的方式来处理动态类型的数据。

以下是 std::any 的一些主要特点:

  1. 可以存储任意类型的值: std::any 可以存储任何类型的值,包括基本数据类型、自定义类型、数组、指针等。

  2. 类型安全: 与使用 void* 相比, std::any 提供了更好的类型安全性。它会在运行时检查访问是否合法,从而避免未定义的行为。

  3. 无需手动内存管理: std::any 会自动管理其包含的值的生命周期,开发者不需要手动分配或释放内存。

  4. 支持赋值和拷贝: std::any 支持赋值和拷贝操作,这使得它可以很方便地在代码中传递和存储值。

示例

#include <iostream>
#include <any>
#include <variant>
#include <string>int main() {// 使用 std::anystd::any anyValue = 42;std::cout << "std::any value: " << std::any_cast<int>(anyValue) << std::endl;anyValue = std::string("hello");std::cout << "std::any value: " << std::any_cast<std::string>(anyValue) << std::endl;// 使用 std::variantstd::variant<int, std::string> variantValue = 42;std::cout << "std::variant value: " << std::get<int>(variantValue) << std::endl;variantValue = std::string("hello");std::cout << "std::variant value: " << std::get<std::string>(variantValue) << std::endl;return 0;
}

anyvariant区别

std::anystd::variant 都是 C++17 引入的非常有用的类型,但它们在功能和使用场景上有一些区别:

  1. 存储类型:

    • std::any 可以存储任意类型的值,包括自定义类型、数组、指针等

    • std::variant 只能存储在定义时指定的有限个类型中的一种

  2. 类型安全:

    • std::any 提供了运行时类型检查,通过 std::any_cast 访问时会检查类型是否匹配,不匹配则抛出 std::bad_any_cast 异常。

    • std::variant 则是在编译时就确定了可能存储的类型,通过 std::get 等函数访问时也可以在编译时检查类型是否匹配。

  3. 访问方式:

    • std::any 通过 std::any_cast 进行访问,需要显式指定类型。

    • std::variant 可以使用 std::getstd::visit 等多种方式进行访问。

  4. 使用场景:

    • std::any 适用于需要处理动态类型数据的场景,如插件系统、配置文件解析等

    • std::variant 则更适用于在有限的几种类型之间进行选择的场景,如函数重载、状态机等。

隐藏转换

这个模块可谓是本文的重点,坑点是最多的。

临时对象具体化 抛砖

        在 C++ 中,临时对象的具体化是一个非常重要的概念。临时对象是在表达式求值过程中创建的短暂对象,它们通常会在表达式结束后被销毁。

std::string getStr() {return "hello";
}
std::string s = getStr(); // 临时对象被具体化并赋值给s
在这个例子中, getStr() 函数返回一个临时的 std::string 对象,该对象会在 main()
函数中被具体化并赋值给 s。int x = 1, y = 2;
int z = x + y; // 临时对象被具体化并赋值给z
在这个例子中,x + y 表达式创建了一个临时的 int 对象,该对象会被具体化并赋值给 z。std::function<int(int)> get_lambda() {return [](int x) { return x * x; };
}
auto square_lambda = get_lambda();
int result = square_lambda(5); // 结果是 25在这个例子中:
1. `get_lambda()` 函数返回一个 lambda 表达式。
2. 这个 lambda 表达式产生了一个临时的 lambda 对象。
3. 这个临时的 lambda 对象被用于初始化 `square_lambda` 变量。
这个临时的 lambda 对象就是通过"临时对象具体化"的过程产生的。编译器会确保这个临时对象的生命周期足够长,以满足初始化 `square_lambda` 的需求。

保证拷贝省略 引玉

        保证拷贝省略(Guaranteed Copy Elision, GCE)并不是 C++17 引入的新特性,它实际上是在 C++11 中引入的。

  C++11中引入了以下几种情况下的拷贝省略:

  1. 返回值优化(RVO):

    • 当函数返回一个局部对象时,编译器可以直接在调用方的位置构造该对象,而无需进行拷贝。
  2. 移动语义优化:

    • 当返回一个临时对象时,编译器可以使用移动构造函数而不是拷贝构造函数
  3. 构造函数参数优化:

    • 当构造函数的参数是一个临时对象时,编译器可以直接在目标位置构造该对象,而无需进行拷贝。

C++17进一步扩展了拷贝省略的范围,增加了以下几种情况:

  1. 无参数构造函数拷贝省略:

    • 当函数返回一个局部对象,且该对象没有参数的构造函数时,编译器可以直接在调用方的位置构造该对象,而无需进行拷贝。
  2. 聚合类型拷贝省略:

    • 当函数返回一个聚合类型(如数组或结构体)的局部对象时,编译器可以直接在调用方的位置构造该对象,而无需进行拷贝。

总的来说,C++11和C++17中的拷贝省略优化可以显著提高程序的性能,减少不必要的拷贝操作。编译器会自动进行这些优化,开发者无需手动干预。

性能优化巅峰   

先举个例子

#include <iostream>class Noisy {
public:Noisy() { std::cout << "Noisy object constructed at " << this << '\n'; }Noisy(const Noisy& other) {std::cout << "Noisy object copy-constructed at " << this << '\n';}Noisy(Noisy&& other) noexcept {std::cout << "Noisy object move-constructed at " << this << '\n';}Noisy& operator=(const Noisy& other) {if (this != &other) {std::cout << "Noisy object copy-assigned at " << this << '\n';}return *this;}Noisy& operator=(Noisy&& other) noexcept {if (this != &other) {std::cout << "Noisy object move-assigned at " << this << '\n';}return *this;}~Noisy() {std::cout << "Noisy object destructed at " << this << '\n';}
};Noisy f(){// c11传统调用 创建一个临时 Noisy 对象,然后将其拷贝构造或移动构造到 v 中    // c17 编译器可以直接在 v 上构造 Noisy 对象,省略掉不必要的拷贝/移动操作。 称为(since C++17) "保证拷贝省略"Noisy v = Noisy();   //注意这里没有任何函数调用!!! 它是怎么做到给返回值给变量v赋值的??
/*
解答:
1.编译器识别到 Noisy v = Noisy(); 是一个直接初始化语句。 
2.它会在 v 的位置直接构造一个 Noisy 对象(Noisy v),而不是先创建一个临时对象,然后再拷贝或移动到 v 中。
3.这个构造过程会调用 Noisy 类的默认构造函数,输出 "Noisy object constructed at 0x[地址]"。
4.最终,v 就直接成为一个 Noisy 类型的对象,不需要经过任何拷贝或移动操作。
*/ return v; 
}void g(Noisy arg)
{std::cout << "&arg = " << &arg << '\n';
}int main()
{// c11  会执行一次拷贝或移动操作,将 v 的内容复制或移动到返回值中。//C++17引入命名返回值优化( NRVO)允许编译器直接在返回值位置构造对象(不调用构造函数),避免不必要的拷贝或移动。Noisy v = f();  //同理 f()返回值v 如何实现给v初始化的?/*
如果 f() 返回一个临时 Noisy 对象或者返回一个命名的 Noisy 对象(例如一个局部变量),编译器会尝试应用 RVO 和 NRVO 等优化,
尽量避免不必要的拷贝和移动操作。
编译器可以直接在 v 的位置构造这个返回的 Noisy 对象,避免任何拷贝或移动。
*/              std::cout << "&v = " << &v << '\n';g(f());// (since C++17)  "拷贝省略"
}

输出


constructed at 0x7fff1d765096    解释:代码行 Noisy v = Noisy(); 的调用
&v = 0x7fff1d765096
constructed at 0x7fff1d765097    解释:代码行 Noisy v = Noisy(); 的调用
&arg = 0x7fff1d765097destructed at 0x7fff1d765097
destructed at 0x7fff1d765096

 C++11 和 C++17 在这些优化上的差异:

  1. 临时变量的初始化:

    • C++11 及更早的版本中,Noisy v = Noisy(); 会先创建一个临时 Noisy 对象,然后将其拷贝或移动到 v 中。这会涉及一次构造和一次拷贝/移动操作。
    • C++17 引入了"保证拷贝省略"(Guaranteed Copy Elision, GCE)特性,编译器可以直接在 v 上构造 Noisy 对象,省略掉不必要的拷贝/移动操作。
  2. 函数返回值的优化:

    • C++11 及更早的版本中,return v; 会执行一次拷贝或移动操作,将 v 的内容复制或移动到返回值中。
    • C++17 引入的"命名返回值优化"(Named Return Value Optimization, NRVO)允许编译器直接在返回值位置构造对象,避免不必要的拷贝或移动。
  3. 函数参数的传递:

    • C++11 及更早的版本中,g(f()); 会先创建一个临时 Noisy 对象,然后将其拷贝或移动到 arg 中。
    • C++17 的"拷贝省略"(Copy Elision)特性允许编译器直接在 arg 上构造 Noisy 对象,避免不必要的拷贝或移动。

 上列的例子,应该能让读者更清楚的对c17”保证拷贝省略“进一步的理解,最后我们在整理一下思路,

临时变量的初始化: Noisy v = Noisy()  -> Nosiy v(); 
函数返回值的优化: Noisy v = {Noisy v; return v;} -> Nosiy v(); 
函数参数的传递:主函数 nrvo优化:
Noisy v = f(); -> 
Noisy v = {Noisy v = Noisy();  return v; }->   //临时变量初始化的优化
Noisy v = {Noisy v();  return v; } -> 
Noisy v = {return v} ->                      //函数返回值的优化
Noisy v = Noisy() ->  
Noisy v;g(f())
g(Noisy arg = {Noisy v = Noisy();  return v;})
g(Noisy arg =  {Noisy v();  return v;})
g(Noisy  arg )

隐式转换

C++ 隐式转换的内容总结如下:

  1. 隐式转换的顺序:

    • 标准转换序列 - 包括值转换和一些数值转换

    • 用户定义转换 - 通过单参数构造函数或转换函数进行

    • 可能的额外标准转换序列

  2. 值转换:

    • 左值到右值

    • 数组到指针

    • 函数到指针

    • 临时对象化 - 将右值转换为左值

  3. 整数提升:

    • 将小整数类型提升为 int 或 unsigned int

  4. 浮点提升:

    • float 转换为 double

  5. 数值转换:

    • 整数间转换

    • 浮点间转换

    • 浮点和整数间转换

    • 指针间转换

    • 指针到成员间转换

    • 布尔转换

  6. 限定符转换:

    • 在相似类型间添加或删除 const/volatile 限定符

  7. 上下文转换:

    • 在特定上下文中进行的隐式转换,如条件表达式、逻辑运算符等

举例

标准转换序列:
int x = 3.14; // float 到 int 的隐式转换用户定义转换:
class Rational {
public:Rational(int numerator, int denominator = 1) {// 用户定义的单参数构造函数}
};
Rational r = 5; // int 到 Rational 的隐式转换 5->Rational  因为没加explicit值转换:
int* p = new int[10]; 
int x = p[0]; // 数组到指针的隐式转换,然后左值到右值的隐式转换整数提升:
char c = 'a';int i = c; // char 提升到 int浮点提升:
float f = 3.14f;
double d = f; // float 提升到 double限定符转换:
const int* p = new int;
int* q = const_cast<int*>(p); // 从 const int* 到 int* 的转换上下文转换:
if (Rational r = 5) { // Rational 到 bool 的隐式转换// ...
}

总结

        总的来说,这篇文章全面介绍了C++17中的一些重要语法和概念变化,对于了解和掌握C++17的新特性很有帮助。文章内容丰富,逻辑清晰,可以作为C++17学习的良好参考资料。

http://www.ds6.com.cn/news/15162.html

相关文章:

  • 做会计应关注什么网站网络营销师证
  • 乐清柳市阿里巴巴做网站的百度收录查询接口
  • 蔬菜派送网站怎么做百度竞价排名什么意思
  • 中山网站的建设seo深圳优化
  • 易企互联网站建设郑志平爱站网创始人
  • 上海住房和城乡建设部网站官网草根seo视频大全
  • 公司注册网站官网新媒体运营岗位职责
  • 怎么样做网站 用网站赚钱贵州seo学校
  • 盐城网站建设公司如何做好网络销售技巧
  • wordpress计算几岁几月几天杭州seo建站
  • 电商的网站有几个海外推广方法有哪些
  • 外贸网站建设十大标准外贸网站建站哪些浏览器可以看禁止访问的网站
  • wordpress个人淘客百度搜索引擎优化
  • 网站建设联系电话国内最新新闻摘抄
  • 黑马程序员官方网站排名优化公司哪家好
  • 做网站推荐源创网络互联网营销顾问是做什么的
  • 曲阜住房城乡建设局网站app营销策略都有哪些
  • 天水做网站电话seo定义
  • 廊坊网站推广百度知道合伙人
  • emlog建站教程非国产手机浏览器
  • 日本人真人做真爱的网站网站关键词优化wang
  • 做网站主要步骤网页制作咨询公司
  • 成套小说网站模板中国互联网协会官网
  • 用股票代码做网站的网站seo优化分析
  • 国际知名的论文网站私域流量运营管理
  • weixinqqcom微信官网seo推广软件怎样
  • 响应式网站和自适应网站安徽网络seo
  • 东莞网站制作南城武汉好的seo优化网
  • WordPress大前端top长春网站优化团队
  • 塘厦仿做网站seo岗位职责