Cpp 进阶笔记——2.移动语义
手动创建将亡值 我们继续前面的函数传参的例子,但是我们做一些修改:调用方提供的不再是一个临时对象,而是一个普通的局部对象 12345678910111213void ProcessBuf(Buffer buf) { for (int i = 0; i < buf.size(); i++) { buf.at(i) = 2 * i; } for (int i = 0; i < buf.size(); i++) { std::cout << buf.at(i) << " "; } std::cout << "\n";}void test2() { Buffer a{5}; a.at(0) = 100; ProcessBuf(a);} 程序运行结果如下(这里无所谓是否关闭优化,因为编译器并不敢进行优化) 12345call constructor //...
Cpp 进阶笔记——1.右值引用
我们关注现代C++中比较难以理解的概念:右值引用,移动语义,完美转发等, 这些概念都是C++11之后才提出的,目的是进一步压榨程序的运行期效率,避免某些非必要的临时变量的拷贝构造和析构过程。这些语法是完全针对底层实现的,并不是针对于上层的语义优化,不是为了让程序变得更易读的语法糖。 左值和右值 (1) 在C++中,表达式由一个或多个运算对象通过运算符组成,对表达式求值得到一个结果。 字面量和变量是最简单的表达式,它们的结果就是字面量和变量的值。 一个表达式至少具有如下两个属性: 类型:描述计算产生的值的静态类型 值类别:描述值是如何产生的,以及表达式的行为如何被影响 从语法上检查一个表达式能否给另一个表达式赋值,既需要判断类型之间能否进行转换,还需要判断值类别是否满足要求。在本文中我们不讨论类型问题,重点关注表达式的值类别。 在C语言和C++的早期语法中,值类别被简单分为左值和右值。 简单地说,在一个合法的赋值语句中,等号左边的就是左值表达式,等号右边的就是右值表达式。 在赋值过程中,右值表达式不会被改变,而左值表达式会因为赋值而改变。 1lvalue =...
Cpp 函数API设计
整理一下关于现代化的C++函数API设计的笔记, 我们关注如何设计可读性好,使用安全的函数接口:设计函数接口的名称、参数类型、返回值等。 部分参考现代化的 API 设计指南 基本原则 函数API的设计要满足如下的原则: 向用户传达清晰的语义,保证接口的可读性,避免因为语义不清晰导致用户的错误调用; 向编译器提供更多的信息,尽可能让错误的使用在编译时就被发现,由编译器发出警告或直接导致编译失败。 如果需要考虑: 跨编译器使用:混用不同编译器编译得到的库 跨语言使用:混用C语言和C++,或者将当前的C++库提供给其它语言调用(例如Python) 那么必须保证使用extern "C"提供C语言形式的接口。 函数和参数名称 保持统一的函数名称风格:大驼峰或使用下划线,例如 123void get_date();void SetDate(); 函数名称通常使用动词加名称的形式,避免提供名称相似的函数接口,尤其是不要出现仅有大小写不同的函数接口。 对于参数的命名,遵循统一的规则即可,但是最好保留具体的语义,例如 1void SetDate(int year, int...
C语言 定义和声明
定义和声明 在...
C语言 关于变量和函数的笔记
概述 C语言中的变量可以大致分为4种: (非静态)局部变量 静态局部变量 (非静态)全局变量 静态全局变量 变量的类别由定义的位置和修饰词决定,例如 12345678int s_global = 10; // 全局变量static int s_global_static = 20; // 静态全局变量void fun(){ int s = 100; // 局部变量 static int s_local_static = 200; // 静态局部变量 //...
Cpp 异常处理
C++提供了一套复杂的异常处理机制,虽然很多第三方库都禁止使用异常,但是至少在标准库中广泛采用了异常机制, 因此学习一下相关的语法是有必要的,至于在编程实践中是否采用异常,仍然是值得讨论的。 简单示例 从一个简单的例子开始,这里调用的函数processInput对于非法的输入参数会抛出异常,在main函数中调用时使用try-catch语句块捕获异常进行处理。 123456789101112131415161718192021222324252627#include <iostream>#include <stdexcept>void processInput(int value) { if (value == 0) { throw std::invalid_argument("Input cannot be zero!"); } if (value < 0) { throw std::out_of_range("Input cannot be...
Cpp和Python相互调用
记录一下在Cpp程序和Python脚本中相互调用的方法。 Cpp调用Python 在C++程序中调用Python解释器,包括执行简单Python语句(字符串形式),以及执行整个py脚本(文件形式)。 执行简单命令 最简单的例子:调用Python解释器,输出HelloWorld,C++源文件如下 main.cpp12345678910111213141516#ifdef _DEBUG#undef _DEBUG#include <Python.h>#define _DEBUG 1#else#include <Python.h>#endifint main() { Py_Initialize(); PyRun_SimpleString("print('Hello, world! (from Python)')"); Py_Finalize(); return...
C/Cpp 输出语句的变迁
C语言 printf 这是C语言提供的输出语句,示例如下 1234567#include <stdio.h>int main() { int number = 42; printf("The answer is %d.\n", number); return 0;} printf支持不定参数,占位符采用%d等,常见类型的占位符如下: %c:字符 %s:字符串 %d或%i:(十进制)int %ld:(十进制)`long int`` %lld:(十进制)long long int %u:(十进制)unsigned...
C语言 结构体笔记
关于C语言中的结构体的语法,这是C++自定义类型的基础。 C++的类提供了非常丰富的功能,但是也会尽量兼容C语言的结构体。 简单示例 下面是针对学生信息的结构体的使用示例,包括了结构体对象的定义和读写,以及通过指针传递给函数。 123456789101112131415161718192021222324252627282930313233343536373839#include <stdio.h>#include <string.h>struct Person { char name[50]; int age; double height;};void show(struct Person *person) { printf("Name: %s\n", person->name); printf("Age: %d\n", person->age); printf("Height: %.2f\n",...