C++ Primer

输入和输出

iostream标准库

C++标准库<iostream>,包含了两个基础类型istream和ostream,分别表述输入流和输出流,一个流就是一个字符序列。
cin是istream的的对象;cout,cerr,clog是ostream的对象。cin和cout是标准输入和输出,cerr是输出警告和错误消息,clog是输出程序运行的一般信息。

std::cout << "hello world" << std::endl;

<<运算符左右两侧是两个变量,一个是ostream的对象cout,一个是字符串变量,<<将字符串变量写到了ostream对象中,返回cout这个结果。然后继续计算cout << std::endl;这个语句,将操纵符endl写入cout中,(endl的作用是结束当前行,并将缓冲区刷新到控制台,也就是说cout接收变量不会马上打印,而是存储在缓冲区,当遇到endl时会刷新缓冲区,而‘\n’只有换行效果,没有刷新缓冲区效果。或者使用std::cout.flush()去刷新缓冲区)。

读取数量不定的输入数据

while (std::cin >> value) {
	sum += value;
}

C++11 functional

C++11 引入了 <functional> 标准库头文件,其中包含了一些有关函数对象(function objects)和函数指针的实用工具,以支持更灵活的函数编程和泛型编程。这个库引入了一些重要的类和概念,让函数处理更加方便和类型安全。下面是一些重要的 <functional> 组件和概念:

std::function:std::function 是一个通用的函数包装器,允许将可调用对象(函数、函数指针、成员函数指针等)封装为一个对象,以便能够像普通函数一样进行传递和调用。这对于实现回调函数或参数化函数的目的非常有用。

函数对象(Function Objects):C++中的函数对象是可调用对象,通常是类的实例,实现了函数调用运算符 operator()。C++11 引入了 std::function 之后,函数对象变得更加通用和易于使用。

std::bind:std::bind 允许创建一个函数对象,将参数绑定到函数的参数。这在创建局部函数或用于回调的函数时非常有用,允许你事先绑定一些参数并稍后调用函数。

Lambda 表达式:C++11 引入了 Lambda 表达式,它们允许在代码中内联定义匿名函数。Lambda 表达式使得函数式编程风格更加容易,可以在循环、算法中使用,也可以用作回调函数。

#include <iostream>
#include <functional>

int main() {
    std::function<int(int, int)> add = [](int a, int b) { return a + b; };
    
    auto multiply = std::bind([](int a, int b) { return a * b; }, std::placeholders::_1, 5);
    
    std::cout << "Add: " << add(3, 4) << std::endl;
    std::cout << "Multiply: " << multiply(3) << std::endl;
    
    return 0;
}

C++11 lamada表达式

用于创建匿名函数,通常用于短期、一次性的函数需求。Lambda 表达式的主要目的是以一种更简洁的方式定义函数,通常用于 STL 算法、回调函数和函数式编程。

Lambda 表达式的一般语法如下:

[capture_clause](parameter_list) -> return_type {
    // 函数体
}

capture_clause:用于指定 Lambda 表达式中的变量捕获方式。可以通过值捕获([=])、引用捕获([&])、或特定变量捕获([var])等方式来访问外部作用域中的变量。
parameter_list:Lambda 表达式的参数列表,类似于普通函数的参数。
return_type:可选项,用于指定 Lambda 表达式的返回类型。如果忽略,编译器通常能够根据返回语句自动推断返回类型。
函数体:包含 Lambda 表达式的具体操作,与普通函数体类似。

Lambda 表达式的一个示例:

#include <iostream>

int main() {
    int x = 5;
    int y = 10;

    // Lambda 表达式,以值捕获 x 和 y
    auto add = [x, y]() {
        return x + y;
    };

    // 调用 Lambda 表达式
    int result = add();
    std::cout << "Result: " << result << std::endl;

    return 0;
}

在这个示例中,Lambda 表达式 add 捕获了 x 和 y 的值,并返回它们的和。Lambda 表达式允许你在其内部使用外部变量,并以不同的捕获方式操作这些变量,使得代码更加紧凑和易读

C++11 auto

auto 是 C++11 引入的关键字,用于自动推断变量的类型。它使编程更加方便,减少了需要显式指定变量类型的需求,特别是在处理复杂的数据类型或使用泛型编程时非常有用。

auto i = 42;     // 推断 i 为整数类型
auto name = "John"; // 推断 name 为字符串类型

std::vector<int> numbers = {1, 2, 3, 4, 5};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
    // 使用 auto 推断的迭代器类型
    std::cout << *it << " ";
}

C++11 move

move 是 C++11 引入的关键字,用于实现移动语义,特别是在处理对象的所有权转移和提高性能方面非常有用。它通常与右值引用 (&&) 结合使用。

关键点和用途包括:

移动语义:move 关键字允许将资源(例如动态分配的内存或文件句柄)的所有权从一个对象转移到另一个对象,而不进行深拷贝。这可以显著提高性能,特别是在处理大型数据结构时。

右值引用:通常,move 与右值引用结合使用,右值引用用于标识临时对象或可以"偷窃"资源的对象。这是因为只有右值引用能够与 move 结合使用,以表示移动语义。

int x = 42;
int y = std::move(x); // 使用 move 将 x 的值转移到 y,x 变为未定义状态

避免不必要的拷贝:move 通常用于避免不必要的对象拷贝,从而提高性能。它可以用于标记对象可以"偷窃"资源而不进行深拷贝的情况。

标准库中的应用:C++标准库中的许多容器和类型都利用了移动语义,例如 std::vector 的 push_back,std::unique_ptr,std::string 等。

std::vector<int> source = {1, 2, 3};
std::vector<int> destination = std::move(source); // 使用 move 将 source 所有权转移到 destination,source 变为未定义状态,移动后source不可再进行访问

右值引用,左值引用,完美引用

左值引用(Lvalue Reference):

  • 左值是表达式的结果是一个具名对象,通常是一个变量的名称。
  • 左值引用用于引用左值,通常表示对对象的可修改引用。
  • 左值引用使用单个&符号来定义,如 int& ref = x;,其中 ref 是对 x 的左值引用。

右值引用(Rvalue Reference):

  • 右值是表达式的结果是一个临时值或不具名的值,通常是表达式的计算结果。
  • 右值引用用于引用右值,通常表示对可以"偷窃"资源的引用,例如移动语义。
  • 右值引用使用双&&符号来定义,如 int&& rref = 5;,其中 rref 是对 5(右值)的右值引用。

完美引用(Perfect Forwarding):

  • 完美引用是C++11引入的特性,它是右值引用和模板的结合,允许在函数模板中以一种通用的方式传递参数。
  • 完美引用通常在泛型编程中使用,允许将参数引用传递给其他函数,同时保留原始参数的左值或右值属性。
  • 完美引用通常通过std::forward函数来实现,它将参数的引用类型传递给其他函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值