Modern-CPP - Chapter02 - Basics
Modern-CPP - Chapter02 - Basics
课程来源:b站我是龙套小果丁
前半部分
加上
-ftrapv
后,溢出会被捕获,程序会abort1 2 3 4 5 6 7
#include <cstdint> #include <print> int main() { std::uint8_t a = 123; std::println("0x{:x}", reinterpret_cast<std::uintptr_t>(&a)); }
1 2 3 4 5 6 7 8
#include <cstdint> float GetInvSqrt(float num) { int32_t i = *reinterpret_cast<int32_t *>(&num); i = 0x5f3759df - (i >> 1); float y = *reinterpret_cast<float *>(&i); return y * (1.5f - (num * 0.5f * y * y)); }
1 2 3 4 5 6
template <typename T> T ToNetworkByteOrder(T value) { if constexpr (std::endian::native == std::endian::little) { return std::byteswap(value); } return value; }
自行写代码看有无报错即可
函数声明:
1
void func(int (*)(float, double));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <utility> enum class Permission : unsigned int { read = 1 << 0, // 1 write = 1 << 1, // 2 exec = 1 << 2 // 4 }; constexpr Permission operator|(Permission a, Permission b) { return static_cast<Permission>(std::to_underlying(a) | std::to_underlying(b)); } constexpr Permission operator&(Permission a, Permission b) { return static_cast<Permission>(std::to_underlying(a) & std::to_underlying(b)); }
- 值为0,因为等号右边的表达式会先被evaluate
后半部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#include <compare> #include <print> class Vector3 { public: explicit Vector3(float x = 0.0f, float y = 0.0f, float z = 0.0f) : x_{x}, y_{y}, z_{z} {} Vector3 &operator+=(const Vector3 &rhs) noexcept { x_ += rhs.x_; y_ += rhs.y_; z_ += rhs.z_; return *this; } friend Vector3 operator+(const Vector3 &lhs, const Vector3 &rhs) noexcept { return Vector3{lhs.x_ + rhs.x_, lhs.y_ + rhs.y_, lhs.z_ + rhs.z_}; } friend bool operator==(const Vector3 &lhs, const Vector3 &rhs) noexcept { return lhs.lengthSquared() == rhs.lengthSquared(); } friend auto operator<=>(const Vector3 &lhs, const Vector3 &rhs) noexcept { return lhs.lengthSquared() <=> rhs.lengthSquared(); } float lengthSquared() const noexcept { return x_ * x_ + y_ * y_ + z_ * z_; } private: float x_, y_, z_; };
可以,特别地:
1 2 3 4 5 6 7 8
#include <map> #include <string> #include <unordered_map> int main() { std::map<std::string, int> scores{{"Alice", 95}, {"Bob", 89}, {"Carol", 92}}; std::unordered_map<std::string, int> heights{{"Tom", 175}, {"Jerry", 165}}; }
有,因为有虚指针的存在,证明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <print> class A { int x; }; class B { int x; virtual void foo() {} }; int main() { std::println("sizeof(A): {}", sizeof(A)); std::println("sizeof(B): {}", sizeof(B)); }
输出:
1 2
sizeof(A): 4 sizeof(B): 16
这里B的大小为16bytes的原因是内存对齐
不构成,只有返回值类型不同不构成重载;不会有干扰,因为有name mangling的存在,两个函数的identifier并不一样:
1 2 3 4 5 6 7 8
void Test(int); template <typename T> T Test(int); int main() { Test(0); Test<void>(0); return 0; }
编译后:
1 2 3 4 5 6 7 8 9 10
main: pushq %rbp movq %rsp, %rbp movl $0, %edi call _Z4Testi movl $0, %edi call _Z4TestIvET_i movl $0, %eax popq %rbp ret
可以看到两个函数的identifier并不相同
不开
-O2
优化:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Foo::foo(): pushq %rbp movq %rsp, %rbp movq %rdi, -8(%rbp) cmpq $0, -8(%rbp) je .L2 movl $42, %eax jmp .L4 .L2: movl $0, %eax .L4: popq %rbp ret bar(): pushq %rbp movq %rsp, %rbp subq $16, %rsp movq $0, -8(%rbp) movq -8(%rbp), %rax movq %rax, %rdi call Foo::foo() leave ret
开
-O2
优化:1 2 3
bar(): movl $42, %eax ret
开启
-O2
优化后,编译器将this指针默认evaluate为true这在clang的linter里也可以发现:
1
'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true clang(-Wundefined-bool-conversion)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#include <algorithm> #include <cstddef> template <typename T> class Array3D { private: T *data; size_t x_size, y_size, z_size; size_t index(size_t x, size_t y, size_t z) const { return x * (y_size * z_size) + y * z_size + z; } public: Array3D(size_t x, size_t y, size_t z) : x_size{x}, y_size{y}, z_size{z} { data = new T[x * y * z](); } ~Array3D() { delete[] data; } Array3D(const Array3D &other) : x_size{other.x_size}, y_size{other.y_size}, z_size{other.z_size} { size_t total_size = x_size * y_size * z_size; data = new T[total_size]; std::copy(other.data, other.data + total_size, data); } Array3D &operator=(const Array3D &other) { if (this != &other) { T *new_data = new T[other.x_size * other.y_size * other.z_size]; std::copy(other.data, other.data + (other.x_size * other.y_size * other.z_size), new_data); delete[] data; data = new_data; x_size = other.x_size; y_size = other.y_size; z_size = other.z_size; } return *this; } T &operator()(size_t x, size_t y, size_t z) { return data[index(x, y, z)]; } const T &operator()(size_t x, size_t y, size_t z) const { return data[index(x, y, z)]; } };
1 2 3 4 5 6 7 8
void FillFibonacci(std::vector<int> &v) { std::ranges::generate(v.begin(), v.end(), [x = 0, y = 1]() mutable { int next = x + y; x = y; y = next; return x; }); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
enum class Color { red, blue, green }; void PrintColor(Color c) { switch (c) { using enum Color; case red: [[fallthrough]]; case green: std::println("Hello"); break; case blue: std::println("World"); break; } }
1 2 3 4 5
void sort_vec(std::vector<DijkstraInfo> &vec) { std::ranges::sort(vec, [](const DijkstraInfo &a, const DijkstraInfo &b) { return a.distance < b.distance; }); }
可以等价为:
1 2 3 4 5
void sort_vec(std::vector<DijkstraInfo> &vec) { std::ranges::sort(vec, [](const auto &a, const auto &b) { return a.distance < b.distance; }); }
因为
vec
的类型为std::vector<DijkstraInfo>
,编译器能推导出auto的实际类型若有如下函数:
1 2 3
bool Func(const auto &a, const auto &b) { return a.distance < b.distance; }
他不能传入
sort
,因为这是个模版函数,编译器不知道用什么实例函数对于该模版:
1 2 3 4 5
template <typename T> struct Functor { static bool operator()(const T &a, const T &b) { return a.distance < b.distance; } };
必须要进行实例化:
1 2 3
void sort_vec(std::vector<DijkstraInfo> &vec) { std::sort(vec.begin(), vec.end(), Functor<DijkstraInfo>()); }
因为
Functor
是一个类模版,编译器无法推导出具体类型因为传递的是引用,改为值传递即可:
1 2 3 4 5 6
CudaMalloc(&_raw_ptr, _buffer_size); _storage = std::make_shared<NDArrayStorage>(BorrowToMemoryPool( local_device, _raw_ptr, _buffer_size, [raw_ptr = _raw_ptr](DataPtr data_ptr) { hetu::cuda::CUDADeviceGuard guard(local_device.index()); CudaFree(raw_ptr); }));
This post is licensed under CC BY 4.0 by the author.