《现代C++教程》笔记(2)

2023-11-12

2.语言可用性的强化

2.1 常量

nullptr

问题:C++ 不允许直接将 void * 隐式转换到其他类型。但如果编译器尝试把 NULL 定义为 ((void*)0), 那么在下面这句代码中:
char *ch = NULL;
没有了 void * 隐式转换的 C++ 只好将 NULL 定义为 0。而这依然会产生新的问题,将 NULL 定义 成 0 将导致 C++ 中重载特性发生混乱。考虑下面这两个 foo 函数:
void foo(char*); 
void foo(int);
那么 foo(NULL); 这个语句将会去调用 foo(int),从而导致代码违反直觉。
解决:C++11 引入了 nullptr 关键字,专门用来区分空指针、0。而 nullptr 的类型 为 nullptr_t,能够隐式的转换为任何指针或成员指针的类型,也能和他们进行相等或者不等的比较。

constexpr

如果编译器能够在编译时就把这些表达式直接优化并植入到程序运行时,将能增加程序的性能。
#include <iostream> 
#define LEN 10

int len_foo() { 
  int i = 2; 
  return i; 
} 

constexpr int len_foo_constexpr() { 
  return 5; 
}

constexpr int fibonacci(const int n) {
  return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2); 
}

int main() { 
  char arr_1[10]; // 合法 
  char arr_2[LEN]; // 合法
  int len = 10; // 
  char arr_3[len]; // 非法
  const int len_2 = len + 1; 
  constexpr int len_2_constexpr = 1 + 2 + 3; 
  // char arr_4[len_2]; // 非法 
  char arr_4[len_2_constexpr]; // 合法
  // char arr_5[len_foo()+5]; // 非法 
  char arr_6[len_foo_constexpr() + 1]; // 合法
  std::cout << fibonacci(10) << std::endl; // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 
  std::cout << fibonacci(10) << std::endl;
  return 0;
}
char arr_4[len_2] 可能比较令人困惑,因为 len_2 已经被定义为了常量。为什么 char arr_4[len_2] 仍然是非法的呢?这是因为 C++ 标准中数组的长度必须是一个常量表达式,而对 于 len_2 而言,这是一个 const 常数而不是一个常量表达式,因此即便这种行为在大部分编译器中都支持,但是它是一个非法的行为, C++11 引入 constexpr 来解决这个问题;而对于 arr_5 来说,C++98 之前的编译器无法得知 len_foo() 在运行期实际上是返回一个常数,
解决:C++11 提供了 constexpr 让用户显式的声明函数或对象构造函数在编译期会成为常量表达式,这个关键字明确告诉编译器应该去验证 len_foo 在编译期就应该是一个常量表达式。

2.2 变量及其初始化

if/switch 变量声明强化:

在判断条件之前能加上临时变量的初始化
if (初始化语句; 条件)
switch (初始化语句; 条件) 

初始化列表:

问题:在传统 C++ 中, 不同的对象有着不同的初始化方法,例如普通数组、POD (Plain Old Data,即没有构造、析构和虚函 数的类或结构体)类型都可以使用 {} 进行初始化,也就是我们所说的初始化列表。而对于类对象的初始 化,要么需要通过拷贝构造、要么就需要使用 () 进行。这些不同方法都针对各自对象,不能通用。
解决:C++11首先把初始化列表的概念绑定到了类型上,并将其称之为std::initializer_list,允许构造函数或其他函数像参数一样使用初始化列表。
MagicFoo(std::initializer_list<int> list) { 
  for (std::initializer_list<int>::iterator it = list.begin(); 
  it != list.end(); ++it) vec.push_back(*it); 
}

结构化绑定:

结构化绑定提供了类似其他语言中提供的多返回值的功能。
问题:C++11 新增了 std::tuple 容器用于构造一个元组,进而囊括多个返回值。但是,C++11/14 并没有提供一种简单的方法直接从元组中拿到并定义元组中的元素,尽管我们可以使用 std::tie 对元组进行拆包,但我们依然必须非常清楚这个元组包含多少个对象,各个对象是什么类型。
解决:更新之后,可以这样写。
#include <iostream>
#include <tuple>

std::tuple<int, double, std::string> f() { 
  return std::make_tuple(1, 2.3, "456"); 
}

int main() {
  auto [x, y, z] = f(); 
  std::cout << x << ", " << y << ", " << z << std::endl; 
  return 0; 
}

2.3 类型推导

auto

一个最常见的例子就是迭代器。
// 由于 cbegin() 将返回 vector<int>::const_iterator 所以 itr 也应该是 vector<int>::const_iterator 类型
for(vector<int>::const_iterator it = vec.cbegin(); itr != vec.cend(); ++it)
而有了 auto 之后可以:
for (auto it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it)
注意:auto 不能用于函数传参,不能用于推导数组类型。

decltype

是为了解决 auto 关键字只能对变量进行类型推导的缺陷而出现的。它的用法和 typeof 很相似:
decltype(表达式)
if (std::is_same<decltype(x), int>::value) 
  std::cout << "type x == int" << std::endl;

尾返回类型推导

利用 auto 关键 字将返回类型后置
template<typename T, typename U> 
auto add2(T x, U y) -> decltype(x+y){ 
  return x + y; 
}

decltype(auto)

主要用于对转发函数或封装的返回类型进行推导,它使我们无需显式的 指定 decltype 的参数表达式。

2.4 控制流

if constexpr

将 constexpr 这个关键字引入到 if 语句中,允许在代码中声明常量表达式的判断条件,能让程序效率更高。
#include <iostream>
template<typename T> 
auto print_type_info(const T& t) { 
  if constexpr (std::is_integral<T>::value) { 
    return t + 1; 
  } 
  else { 
    return t + 0.001; 
  } 
}
在编译时,实际代码就会表现为如下:
int print_type_info(const int& t) { 
  return t + 1; 
} 
double print_type_info(const double& t) { 
  return t + 0.001; 
}

区间 for 迭代

for (auto element : vec)

2.5 模板

模板的哲学在于将一切能够在编译期处理的问题丢到编译期进行处理,仅在运行时处理那些最核心的动 态服务,进而大幅优化运行期的性能。

外部模板

问题:只要在每个编译单元(文件)中 编译的代码中遇到了被完整定义的模板,都会实例化。这就产生了重复实例化而导致的编译时间的增加。 并且,我们没有办法通知编译器不要触发模板的实例化。
解决:引入了外部模板,扩充了原来的强制编译器在特定位置实例化模板的语法,使我们能 够显式的通知编译器何时进行模板的实例化:
template class std::vector<bool>; // 强行实例化 
extern template class std::vector<double>; // 不在该当前编译文件中实例化模板
尖括号 “>”
问题:在传统 C++ 的编译器中,>> 一律被当做右移运算符来进行处理。但实际上我们很容易就写出了嵌 套模板的代码。
解决: C++11 开始,连续的右尖括号将变得合法,并且能够顺利通过编译。

类型别名模板

问题:typedef 可以为类型定义一个新的名称,但是却没有办法为模板定义一个新的名称。因为,模板不是类型。
解决:C++11 使用 using 引入了下面这种形式的写法,并且同时支持对传统 typedef 相同的功效。通常是 typedef 原名称 新名称;,但是对函数指针等别名的定义语法却不相同,这通常给直接阅读造成了一定程度的困难。
typedef int (*process)(void *); 
using NewProcess = int(*)(void *); 
template<typename T> 
using TrueDarkMagic = MagicType<std::vector<T>, std::string>;

int main() { 
  TrueDarkMagic<bool> you; 
}

默认模板参数

问题:要使用模板函数,就必须每次都指定其模板参数的类型。
解决: C++11 中提供了一种便利,可以指定模板的默认参数
// T 和 U 后面的 = int 就是加的
template<typename T = int, typename U = int> 
auto add(T x, U y) -> decltype(x+y) { 
return x+y; 
}

变长参数模板

问题:无论是类模板 还是函数模板,都只能按其指定的样子,接受一组固定数量的模板参数。
解决: C++11 加入了新的表示方 法,允许任意个数、任意类别的模板参数,同时也不需要在定义时将参数的个数固定。
如果不希望产生的模板参数个数为 0,可以手动的定义至少一个模板参数:
template<typename Require, typename... Args> class Magic;
除了在模板参数中能使用 ... 表示不定长模板参数外, 函数参数也使用同样的表示法代表不定长参数。
对参数进行解包,首先,我们可以使用 sizeof... 来计算参数的个数,
template<typename... Ts> void magic(Ts... args) { 
  std::cout << sizeof...(args) << std::endl; 
}
有两种经典的处理手法:
1. 递归模板函数
#include <iostream> 

template<typename T0> 
void printf1(T0 value) { 
  std::cout << value << std::endl; 
} 

template<typename T, typename... Ts> void printf1(T value, Ts... args) { 
  std::cout << value << std::endl; printf1(args...); 
}
2. 变参模板展开
template<typename T0, typename... T> void printf2(T0 t0, T... t) { 
  std::cout << t0 << std::endl; if constexpr (sizeof...(t) > 0) printf2(t...); 
}
其实,不一定需要对参数做逐个遍历,我们可以利用 std::bind 及完美转发等特性实现对函数和参数的绑定,从而达到成功调用的目的。
3. 初始化列表展开
递归模板函数是一种标准的做法,但缺点显而易见的在于必须定义一个终止递归的函数。
template<typename T, typename... Ts> auto printf3(T value, Ts... args) { 
  std::cout << value << std::endl; 
  // 为了避免编译器警告,我们可以将 std::initializer_list 显式的转为 void
  (void) std::initializer_list<T>{([&args] { 
    std::cout << args << std::endl; 
  }(), value)...}; 
}
使用了C++11 中提供的初始化列表以及 Lambda 表达式。

折叠表达式

将变长参数这种特性进一步带给了表达式
template<typename ... T> auto sum(T ... t) { 
  return (t + ...); 
}

非类型模板参数推导

可以 用auto 关键字,让编译器辅助完成具体类型的推导。

2.6 面向对象

委托构造

构造函数可以在同一个类中一个构造函数调用另一个构造函数
#include <iostream> class Base { 
  public: int value1; 
  int value2; 

  Base() { 
    value1 = 1; 
  } 

  Base(int value) : Base() { // 委托 Base() 构造函数 
    value2 = value; 
  } 
};

继承构造

利用using关键字引入了继承构造
class Subclass : public Base { 
  public: using Base::Base; // 继承构造 
};

显式虚函数重载

问题:在传统 C++ 中,经常容易发生意外重载虚函数的事情,例如
struct Base { 
  virtual void foo(); 
}; 

struct SubClass: Base {
  void foo();
};
SubClass::foo 可能并不是程序员尝试重载虚函数,只是恰好加入了一个具有相同名字的函数。另 一个可能的情形是,当基类的虚函数被删除后,子类拥有旧的函数就不再重载该虚拟函数并摇身一变成 为了一个普通的类方法,这将造成灾难性的后果。
解决:引入了override和final。
override 当重载虚函数时,引入 override 关键字将显式的告知编译器进行重载,编译器将检查基函 数是否存在这样的虚函数,否则将无法通过编译。
struct Base { 
  virtual void foo(int); 
}; 

struct SubClass: Base { 
  virtual void foo(int) override; // 合法 
  virtual void foo(float) override; // 非法, 父类没有此虚函数 
};
final 则是为了防止类被继续继承以及终止虚函数继续重载引入的。
struct Base { 
  virtual void foo() final; 
}; 

struct SubClass1 final: Base { 
}; // 合法 

struct SubClass2 : SubClass1 { 
}; // 非法, SubClass1 已 final

struct SubClass3: Base { 
  void foo(); // 非法, foo 已 final 
};

显式禁用默认函数

传统C++中, 如果程序员没有提供,编译器会默认为对象生成默认构造函数、复制构造、赋值 算符以及析构函数。 另外, C++ 也为所有类定义了诸如 new delete 这样的运算符。当程序员有需要时, 可以重载这部分函数。
这就引发了一些需求:无法精确控制默认函数的生成行为。例如禁止类的拷贝时,必须将复制构造 函数与赋值算符声明为 private 。尝试使用这些未定义的函数将导致编译或链接错误,则是一种非常不优雅的方式。
并且,编译器产生的默认构造函数与用户定义的构造函数无法同时存在。若用户定义了任何构造函 数,编译器将不再生成默认构造函数,但有时候我们却希望同时拥有这两种构造函数,这就造成了尴尬。
C++11 提供了上述需求的解决方案,允许显式的声明采用或拒绝编译器自带的函数。例如:
class Magic {
    public:
    Magic() = default; // 显式声明使用编译器生成的构造
    Magic& operator=(const Magic&) = delete; // 显式声明拒绝编译器生成构造
    Magic(int magic_number);
}

强枚举类型

在传统 C++ 中,枚举类型并非类型安全,枚举类型会被视作整数,则会让两种完全不同的枚举类 型可以进行直接的比较(虽然编译器给出了检查,但并非所有), 甚至同一个命名空间中的不同枚举类型 的枚举值名字不能相同 ,这通常不是我们希望看到的结果。
C++11 引入了枚举类( enumeration class), 并使用 enum class 的语法进行声明:
enum class new_enum : unsigned int {
    value1,
    value2,
    value3 = 100,
    value4 = 100
};
这样定义的枚举实现了类型安全,首先他不能够被隐式的转换为整数,同时也不能够将其与整数数 字进行比较,更不可能对不同的枚举类型的枚举值进行比较。但相同枚举值之间如果指定的值相同,那 么可以进行比较:
if (new_enum::value3 == new_enum::value4) {
    // 会输出
    std::cout << "new_enum::value3 == new_enum::value4" << std::endl;
}
在这个语法中,枚举类型后面使用了冒号及类型关键字来指定枚举中枚举值的类型,这使得我们能 够为枚举赋值(未指定时将默认使用 int )。 而我们希望获得枚举值的值时,将必须显式的进行类型转换,不过我们可以通过重载 << 这个算符来 进行输出,可以收藏下面这个代码段:
#include <iostream>

template<typename T>
std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value,  std::ostream>::type& stream, {
    return stream << static_cast<typename std::underlying_type<T>::type>(e);
}

这时,下面的代码将能够被编译:
std::cout << new_enum::value3 << std::endl

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《现代C++教程》笔记(2) 的相关文章

  • 金特 + XNA (C#)

    是否可以使用jint http jint codeplex com操作使用 XNA C 创建的 3D 环境 并向该环境添加功能 再次使用 jint 作为 Jint 的贡献者 我会推荐你Jint http jint codeplex com
  • Volatile.Read 和 Volatile.Write 背后的逻辑是什么?

    来自 MSDN Volatile Read 读取字段的值 在需要它的系统上 插入一个 阻止处理器重新排序内存的内存屏障 操作如下 如果在该方法之后出现读或写 代码 处理器无法移动它before这个方法 and Volatile Write
  • 在 C# 中使用“using”关键字避免多次处置的最佳实践

    当变量是 IDisposable 时 我们有using关键字来管理处置 但是如果我们在方法中返回值怎么办 using twice StringContent stringToStringContent string str using St
  • WebClient.DownloadDataAsync 冻结了我的 UI

    我在 Form 构造函数中的 InitializeComponent 之后有以下代码 using WebClient client new WebClient client DownloadDataCompleted new Downloa
  • 我如何知道 C 程序的可执行文件是在前台还是后台运行?

    在我的 C 程序中 我想知道我的可执行文件是否像这样在前台运行 a out 或者像这样 a out 如果你是前台工作 getpgrp tcgetpgrp STDOUT FILENO or STDIN FILENO or STDERR FIL
  • 并行化斐波那契序列生成器

    我正在学习并行化 在一项练习中 我得到了一些我应该提高性能的算法 其中之一是斐波那契数列生成器 array 0 0 array 1 1 for q 2 q lt MAX q array q array q 1 array q 2 我怀疑 这
  • 异常堆栈跟踪不显示抛出异常的位置

    通常 当我抛出异常 捕获它并打印出堆栈跟踪时 我会看到抛出异常的调用 导致该异常的调用 导致该异常的调用that 依此类推回到整个程序的根 现在它只向我显示异常所在的调用caught 而不是它所在的地方thrown 我不明白是什么改变导致了
  • 全局使用和 .NET Standard 2.0

    我最近意识到我可以使用 C 10 功能文件范围的命名空间在 NET Standard 2 0 项目中也可以通过设置
  • 带有运算符语法的错误消息,但不带有函数语法的错误消息

    为什么我在调用 unary 时收到错误消息 使用运算符语法 如果我用函数语法调用它就可以了 现场演示 https godbolt org z j7AbeQ template
  • C# 编译器数字文字

    有谁知道 C 编译器数字文字修饰符的完整列表 默认情况下 声明 0 使其成为 Int32 声明 0 0 使其成为 Double 我可以在末尾使用文字修饰符 f 来确保某些内容被视为 Single 例如像这样 var x 0 x is Int
  • 通过 C# Mailkit / Mimekit 发送电子邮件,但出现服务器证书错误

    Visual Studio 2015 中的 0 代码 1 我正在使用 Mailkit 最新版本 1 18 1 1 从我自己的电子邮件服务器发送电子邮件 2 电子邮件服务器具有不受信任的自签名证书 3 我在代码中添加了以下两行 以忽略服务器证
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • 无法为 wsdl 文件创建服务引用

    I have wsdl文件和xsd我本地机器上的文件 我想在项目中添加服务引用 我没有网络服务 我只有wsdl file 我收到以下错误 The document was understood but it could not be pro
  • 使用多线程进行矩阵乘法?

    我应该使用线程将两个矩阵相乘 有两件事 当我运行程序时 我不断得到 0 我还收到消息错误 对于每个错误 它在粗体行上显示 警告 从不兼容的指针类型传递 printMatrix 的参数1 我尝试打印输出 还要注意 第一个粗体块 这是我解决问题
  • C# 中的 C/C++ 代码编译器

    在 C 中 我可以使用下面的代码编译 VB 和 C 代码 但无法编译 C C 代码 有什么办法可以做到这一点吗 C 编译器 public void Compile string ToCompile string Result null st
  • Autoconf 问题:“错误:C 编译器无法创建可执行文件”

    我正在尝试使用 GNU 自动工具构建一个用 C 编写的程序 但显然我设置错误 因为当configure运行 它吐出 configure error C compiler cannot create executables 如果我看进去con
  • “必须声明标量变量”错误[重复]

    这个问题在这里已经有答案了 必须声明标量变量 Id SqlConnection con new SqlConnection connectionstring con Open SqlCommand cmd new SqlCommand cm
  • 无法识别解决方案文件夹中的 Visual Studio 2017 Nuget.config

    我在使用 Visual Studio 2017 时遇到问题 新的解决方案不断引用 C Users yopa AppData Roaming NuGet Nuget config 中意外位置的 Nuget config 文件 我已将 nuge
  • 如果“嵌入式”SQL 2008 数据库文件不存在,如何创建它?

    我使用 C ADO Net 和在 Server Management Studio 中创建的嵌入式 MS SQL 2008 数据库文件 附加到 MS SQL 2008 Express 创建了一个数据库应用程序 有人可以向我指出一个资源 该资
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可

随机推荐

  • 【Spring基础】@Configuration和@Import

    起因 偶然间 用到了 Configuration创建Bean 对于 Configuration又学到了一些知识点 单例模式 网上查资料 理解有误差 以为单例模式一个类只有一个实例 只能创建一个Bean 但是如果同一个类需要创建多个对象的时候
  • spring boot上传文件-参数注入对象

    1 pom xml依赖
  • Spring mvc4使用jackson绑定controller返回

    1 spring MVC4以上 使用的json包有变更 2 使用之前的json包出现Java lang NoClassDefFoundError com fasterxml jackson core JsonProcessingExcept
  • IDEA中项目结构出现:0% classes,0% lines covered ,怎样去除?

    文章目录 1 现象 2 原因分析 3 去除解决 1 现象 IDEA中项目结构出现 0 classes 0 lines covered 2 原因分析 我是在启动项目的时候 点击了下图按钮 run with coverage 这是可以进行覆盖率
  • (大集合)Linux进程和线程的基本编程、通讯和例程【杂记】

    Linux 进程 和 线程 的基本 编程 通讯 和 例程 注 杂记 系列为日常网搜资料的堆砌而积累成之 如有错误恭谢指出 标识为 原创 其实不完全是 只是多引用再整理和加上自己的理解 进行记录备查 大都引自网络 侵删 大量参考 100ask
  • Yarn基础知识(个人总结)

    声明 1 本文为我的个人复习总结 并非那种从零基础开始普及知识 内容详细全面 言辞官方的文章 2 由于是个人总结 所以用最精简的话语来写文章 3 若有错误不当之处 请指出 Yarn架构 Yarn集群有一个ResourceManager 每台
  • 基于vue实现钉钉审批流程(仿)

    做项目有个需求 实现审批流程 看了钉钉审批流感觉功能很强大 模仿其实现审批效果 效果图 没有找到windows录制视频转gif的软件 所以只能放一张静图了 有好的软件欢迎各位积极分享 代码位置 整个流程上传至github https git
  • 数据库字段为什么要使用NOT NULL

    目录 1 对程序的影响 2 对查询结果的影响 2 1 聚合函数count 不准确 2 1 与 失效 2 3 NULL与其他值运算结果为NULL 2 4 对distinct group by order by等排序结果的影响 3 对索引的影响
  • html文本延迟加载,LazyLoad 延迟加载(按需加载)

    1 实际需求 大型网站往往很矛盾 想用户在首页看到更多东西 又不想浪费太多服务器流量 比如一个有3屏的首页 可能50 的用户进首页的目的是点击首页的连接 到子页面 那么我们的网站却为100 的用户加载了 3个 屏幕的所有内容 如果可以按需加
  • HIT-ICS2019大作业-程序人生-Hello’s P2P

    HIT ICS2019大作业 程序人生 Hello s P2P 摘 要 本文以一个简单的C程序hello c为楔子描绘了从预处理一直到I O管理的计算机的内部原理 将计算机对程序的处理过程生动地展现在人们眼前 关键词 hello 程序 P2
  • 1157:哥德巴赫猜想(C C++)

    题目描述 哥德巴赫猜想的命题之一是 大于6 的偶数等于两个素数之和 编程将6 100所有偶数表示成两个素数之和 输入 无 输出 分行输出 例如 6 3 3 8 3 5 每个数只拆开一次 请保证第一个加数最小 输入样例 无 输出样例 无 代码
  • Simulink 学习(一)

    一 基本操作 Simulink多用于仿真 分为模块 输入 输出 matlab中 有两种方法打开 第一种就如图所示 第二种直接在命令窗口输入 simulink 模块库 例如 常量倍数放大利用Math Oprations中的Gain模块 双击可
  • koa-view架构分析

    根据后端的模板引擎渲染到模板上 如ejs 安装 npm install koa views save registry https registry npm taobao org 安装ejs npm install ejs save reg
  • Gin框架使用Casbin进行用户权限校验

    以下是测试项目目录 一 配置model conf casbin rbac model conf 请求 request definition r sub obj act sub gt 想要访问资源的用户角色 Subject 请求实体 obj
  • TensorFlow学习笔记2-Anaconda下安装matplotlib的方法

    文章在下述博文的基础上删减 http blog csdn net abvedu article details 54731713 安装好Anaconda后 在Anaconda Prompt下执行conda命令安装matplotlib包 执行
  • JavaScript 宏任务和微任务

    JavaScript 宏观任务和微观任务 概念 宏观任务 宿主发起的任务为宏观任务 如setTimeout setInterval setImmediate I O 微观任务 JavaScript引擎发起的任务为微观任务 如Promise
  • 计算机组成原理——指令系统题库

    指令系统题库 选择题 1 以下有关指令系统的说法中错误的是什么 A 指令系统是一台机器硬件能执行的指令全体 B 任何程序运行前都要先转化为机器语言 C 指令系统是计算机软件 硬件的界面 D 指令系统和机器语言是无关的 2 在CPU执行指令的
  • tip消息定时弹窗功能 核心代码

    for var i 0 i lt 5 i var j 0 var arr 1 2 5 7 8 setTimeout function console log arr j i 3000
  • 深度学习与神经网络笔记

    在正式学习之前 首先清楚一下当前出现了很多次的概念是什么 这些概念之间的关系是什么 人工智能 AI 研究 开发用于模拟 延伸和扩展人的智能的理论 方法 技术和应用系统的一门新的技术科学 机器学习 实现人工智能的一种途径 以机器学习为手段解决
  • 《现代C++教程》笔记(2)

    2 语言可用性的强化 2 1 常量 nullptr 问题 C 不允许直接将 void 隐式转换到其他类型 但如果编译器尝试把 NULL 定义为 void 0 那么在下面这句代码中 char ch NULL 没有了 void 隐式转换的 C