公众号
RSS https://github.com/wanghenshui/cppweeklynews/releases.atom
欢迎投稿,推荐或自荐文章/软件/资源等
20230128 唉,不想上班
还是介绍c++23特性,鉴于中文资料还是比较少的,这里推荐一下
之前咱们也讲过很多次别名引入导致的性能低下,编译期不能充分优化的问题。这里又科普一遍,还有谁不知道?
simd指令教学,感兴趣的可以看看
https://godbolt.org/z/PPsn4KM7Y
简单来说还是embed,借助embed实现concept reflexpr
讨论optional各种构造转换
https://godbolt.org/z/zKbWc7MhE
https://godbolt.org/z/5ajjYs754
直接贴代码了。很复杂,值得研究一波
老文,讲了一些c++20的改进,比如constexpr
#include <iostream>
#include <variant>
constexpr std::variant<int, double> foo(int x) {
std::variant<int, double> oi { x * 0.1 };
if (x > 10)
oi = x;
return oi;
}
int main() {
constexpr auto dv = foo(1);
static_assert(std::holds_alternative<double>(dv));
constexpr auto iv = foo(100);
static_assert(std::holds_alternative<int>(iv));
}
再比如经典坑
std::variant<string, bool> x = "abc"; // 此时的x是bool,惊不惊喜
修订在这 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r3.html
一些维护大项目的经验,比如ccache加速CICD,项目组织以及重用代码,甚至给了一个cmake模板 https://github.com/tfc/cmake_cpp_example
看着还不错
Raymond chen又发了一堆winrt的文章,我不了解,没细读,这里直接贴出来
对OI感兴趣的可以看看,有几个模板库 比如这个https://github.com/emthrm/cp-library
看个乐
感兴趣可以看看
温故知新
树的几种遍历,针对递归型,什么遍历,就在什么位置调用
如果是非递归用堆栈,前序遍历,那就堆栈里放left/right,后序遍历,那堆栈就放当前节点,中序遍历,那就先放left,放完了也就定好顺序了,访问节点和right就行了
我这里描述的非常模糊,边界条件也没说,不懂的话找个代码看看,我说个大概意思
在执行main之前还会执行别的动作。就是利用这个性质来打印。说实话一般
就是基于cling的一个python内调用c++的工具。cling有句讲句活跃程度堪忧
>>> import cppyy
>>> cppyy.cppdef("""
... class MyClass {
... public:
... MyClass(int i) : m_data(i) {}
... virtual ~MyClass() {}
... virtual int add_int(int i) { return m_data + i; }
... int m_data;
... };""")
True
>>> from cppyy.gbl import MyClass
>>> m = MyClass(42)
>>> cppyy.cppdef("""
... void say_hello(MyClass* m) {
... std::cout << "Hello, the number is: " << m->m_data << std::endl;
... }""")
True
>>> MyClass.say_hello = cppyy.gbl.say_hello
>>> m.say_hello()
Hello, the number is: 42
>>> m.m_data = 13
>>> m.say_hello()
Hello, the number is: 13
>>> class PyMyClass(MyClass):
... def add_int(self, i): # python side override (CPython only)
... return self.m_data + 2*i
...
>>> cppyy.cppdef("int callback(MyClass* m, int i) { return m->add_int(i); }")
True
>>> cppyy.gbl.callback(m, 2) # calls C++ add_int
15
>>> cppyy.gbl.callback(PyMyClass(1), 2) # calls Python-side override
5
鉴于我们是c++周刊,python代码就不多列举了。大家感兴趣的自己玩玩
我没懂,这种和经典singleton有啥不一样吗,哦singleton全局的
gdb结合tui,结合python等等,没总结,感兴趣的可以看看
ppt在这里 https://www.jonathanmueller.dev/talk/meetingcpp2022/
作者在搞一个脚本语言虚拟机,对比switch,改成jumptable带来很大受益,讲的就是这个调优过程
话说回来,不看视频只看ppt的话 https://meetingcpp.com/mcpp/slides/?year=2022 这里有挺有有意思的
比如这个 https://meetingcpp.com/mcpp/slides/2022/Basic%20usage%20of%20PMRs%20for%20better%20performance8308.pdf
我觉得非常值得一看
我觉得还是直接看ppt吧,非常容易懂,我记得以前godbolt也讲过类似的主题
https://knatten.org/download/Anders%20Schau%20Knatten%20-%20Just%20Enough%20Assembly%20for%20Compiler%20Explorer%20-%20Meeting%20C++%202022.pdf
我贴一下代码
;--- 经典寄存器使用
mov rdi, 2
mov rsi, 4
add rdi, rsi
;结果 rdi 6, rsi 4
;--- 堆栈push/pop
mov rdi, 0xfedcba9876543210
push rdi
pop rsi
;结果 rsi=rdi=0xfedcba9876543210,经典赋值,两条指令,mov要多用一个寄存器/地址中转
;--- 访问地址
mov rsi, 0x3333333333333333
mov rdi, 0x2222222222222222
mov qword ptr [rsp - 8], rsi
add rdi, qword ptr [rsp - 8]
;这里数组括号就是访问地址,把rsi弄到rsp-8的位置存一下,然后 add访问哪个地址的值,也就是rsi的值,加到rdi
; rdi 0x5555555555555555, rsi不变
; 为什么-8 因为rsi都是64位的寄存器
; byte: rax 8 eax 4 ax 2 al/ah 1
;来一个32位的例子
mov esi, 0x3333333333333333
mov edi, 0x2222222222222222
mov dword ptr [rsp - 8], esi
add edi, dword ptr [rsp - 8]
;结果就不说了
;再来一个word例子
mov word ptr [rsp-8], 0x1111
mov word ptr [rsp-6], 0x2222
mov word ptr [rsp-4], 0x3333
mov word ptr [rsp-2], 0x4444
lea rdi, [rsp-8] ; rdi指向rsp-8这个位置了
mov ax, word ptr [rdi+6] ; ax 0x4444懂吧
mov rsi, 0
mov ax, word ptr [rdi+rsi*2] ; 0x1111
inc rsi
mov ax, word ptr [rdi+rsi*2] ; 0x2222
;---- 条件
mov rsi, 2
mov rdi, 3
cmp rdi, rsi ;和j命令配合不满足继续走到jmp
jg .greater
mov rax, 0
jmp .endif
.greater:
mov rax, 1
.endif:
;---- 循环
; c代码这样
; int rax=0;
; for (int rcx=1;rcx!=3;++rcx) {rax += rcx;}
mov rax, 0
mov rcx, 1
.for
cmp rcx, 3
je .endfor
add rax, rcx
inc rcx
jmp .for
.endfor
;---- 来个函数
;int sum(int a, int b){ return a + b;}
sum(int, int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-8]
add eax, edx
pop rbp
ret
;能看懂吧,另外优化后肯定能看懂,省掉把入参传到栈上来回折腾的流程了
sum(int, int):
lea eax, [rdi+rsi]
ret
再来个例子,调用函数
;int times_two(int i);
;int sum_times_two(int a, int b){ return times_two(a + b);}
;int times_two(int i){ return i*2;}
sum_times_two(int, int):
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-8]
add eax, edx
mov edi, eax
call times_two(int) ;看edi的用法
leave
ret
times_two(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
add eax, eax
pop rbp
ret
目前没看着有啥好工作,尽量别被开吧
如果有疑问评论最好在上面链接到评论区里评论,这样方便搜索,微信公众号有点封闭/知乎吞评论