Skip to content

Commit

Permalink
2023-12-07
Browse files Browse the repository at this point in the history
  • Loading branch information
XieYHccc committed Dec 8, 2023
1 parent 592ce52 commit 1d9d508
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
15 changes: 5 additions & 10 deletions _posts/2023-12-07-Copy-And-Move-Semantics.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,27 @@
## 拷贝构造函数和拷贝赋值运算符的行为

* **默认拷贝构造函数/拷贝赋值运算符**

不同的类成员执行不同的操作:

* Class type:调用该类成员的拷贝构造函数/拷贝赋值运算符

* C array:挨个元素拷贝/赋值
* Scalar type(int, float等等):调用内置赋值运算符

* **显示定义了拷贝构造函数/拷贝赋值运算符**

所有行为均由用户定义。只有显示使用初始化列表拷贝构造/赋值类成员,才会调用类成员的拷贝构造/赋值

## 移动构造函数/移动赋值运算符的行为

* **默认移动构造函数/移动赋值运算符**
* Class type:调用该类成员的移动构造函数/移动赋值运算符
* **C array:挨个元素拷贝/赋值**
* **Scalar type(int, float等等):调用内置赋值函数**

* 显示定义了移动构造函数/移动赋值运算符
* C array:挨个元素拷贝/赋值
* Scalar type(int, float等等):调用内置赋值函数

* **显示定义了移动构造函数/移动赋值运算符**
所有行为均由用户定义。只有显示使用初始化列表移动构造/移动赋值类成员,才会调用类成员的移动构造函数/移动赋值运算符

## 误区

* 只有class type才有拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符。C array和Scalar type不管是在拷贝语义还是移动语义里其实都只是在做赋值(个人认为对这两个类型拷贝和赋值是一个东西)罢了。
* 只有class type才有拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符。C array和Scalar type不管是在拷贝语义还是移动语义里其实都只是在做赋值

* 将一个类和它的的class type 成员递归展开,如果没有指针/资源,则移动语义没有意义,移动构造函数等价于拷贝构造函数,移动赋值函数等于移动赋值函数。

* 栈中数据的内存大小和位置是固定的,位置是相对于栈起始位置的偏移,因此 std::array<int, 5> a = std::move(b)没有意义,并不会把a变量改成b的地址和大小。(我之前竟然有这个想法...真是太蠢了)
10 changes: 8 additions & 2 deletions _posts/2023-12-07-Write-A-Math-Libraray-In-C++.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,30 @@

* C风格数组没有类型,只是一块内存,并没有过多的语义。对C数组使用索引取值其实是在移动指针,该索引值可以是任意整数,包括负整数,因为移动指针我们既可以向后移动也可以向前移动。

* std::array是对C数组的封装,C数组是其唯一的数据,但std::array是一个类型,所以其可以作为函数的参数和返回值,这比C风格数组方便很多。std::array拥有了值的语义,且索引必须是正整数,比如说第一个值第二个值等等。std::array 有很多好用的接口,比如说size(), range-based for loop等等
* std::array是对C数组的封装,C数组是其唯一的数据,但std::array是一个类型,所以其可以作为函数的参数和返回值,这比C风格数组方便很多。std::array拥有了值的语义,且索引必须是正整数,比如说第一个值第二个值等等。std::array 有很多好用的接口,比如说size(), range-based for loop等等。

* 减少犯错的角度:直接操纵C数组其实就是在操纵内存,编译器不会帮助我们检查错误,很容易犯错。

* 性能:我在Mac M1 Max 做了测试。在Debug模式下C风格数组比std::array快很多,在Release模式下两者没差异,都快得离谱:)

* 结论:能用std::array就用std::array,不用过多担心c++性能问题,编译器的Release会将c++的东西优化的很快。

## size_t vs int vs unsigned int vs ptr_diff

之所以会出现这个问题,是我在选取索引类型是遇到了困难。

* size_t 和unsigned int 均为无符号整数,int是有符号整数。当设计需要索引值可以取负数时,size_t和unsigned int 可以被排除,int也不推荐,建议使用ptr_diff,因为其定义上更为合理,索引的本质其实是在移动指针。(本人对ptr_diff并无过多了解,我不打算让索引可以取负值)
* size_t 和unsigned int 均为无符号整数,int是有符号整数。当设计需要索引值可以取负数时,size_t和unsigned int 可以被排除,int也不推荐,建议使用ptr_diff,因为其定义上更为合理,索引的本质其实是在移动指针。(本人对ptr_diff并无过多了解,我不打算让索引可以取负值)

* 在64位电脑上,int和unsigned int均为四个byte 大小,size_t为8个byte大小,这意味着size_t能表示比unsigned int 更大的整数。因此,想要设计一个大容量容器时,采用size_t更合理。

* size_t是stl容器大小的返回类型,当底层容器是stl容器时,为了保持统一性,选择size_t作为索引值更合理。



## std::copy vs memcopy

* 用C的函数直接操纵内存确实快,但用C++标准库的函数在Release模式下和C函数一样快,因为编译器会对标准库函数进行优化,有时候会把标准库函数编译为C函数。除此之外,编译器还有很多我不清楚的优化,因此可能比我直接用C函数还快(我是小白)。

* 结论:对我这种小白来说,能用C++标准库的函数就用C++标准库的函数。当然有时候可能也不想为了一个函数而include一个头文件。

## 从空间的角度设计数学库
Expand Down

0 comments on commit 1d9d508

Please sign in to comment.