undefined

编译命令行

1
2
GCC: g++ -std=c++17 -W -Wall -Wfatal-errors 文件名
clang: clang++ -std=c++17 -W -Wall -Wfatal-errors 文件名

好书推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
入门介绍
《c++语言导学》《深入理解C++11:C++11新特性解析与应用》
最佳实践
《Effective C++中文版》《Effective STL中文版》《Effective Modern C++中文版》
深入学习
《Exceptional C++中文版》《C++编程规范: 101条规则准则与最佳实践》《STL源码剖析》
高级专题
《数学与泛型编程:高效编程的奥秘》《C++设计新思维》
《Anthony Williams,C++Concurrency in Action,2nd ed. Manning,2019 英文版》
《C++函数式编程》
参考书
《C++程序设计语言》《C++标准库》
C++的设计哲学
《C++语言的设计与演化》《C++编程思想》
其他
《设计模式》《UNIX编程艺术》《软件工艺》《黑客与画家》《代码整洁之道》

查看更多

undefined

一、格式化工具

1. Clang-Format

在项目中放上 .clang-format 这个文件,就可以处理代码的格式化了。

clang-format 的使用:https://www.cnblogs.com/__tudou__/p/13322854.html

2. clang-tidy

mac 上安装clang-tidy 比较麻烦,如下安装

https://stackoverflow.com/questions/53111082/how-to-install-clang-tidy-on-macos

3. Cppcheck

较 clang-tidy 轻量的工具,运行速度快。它和clang-tidy 的重点不太一样:它强调的是发现代码可能出现问题的地方,而不太着重代码风格问题,两者功能并不完全重叠。有条件的情况下,这两个工具可以一起使用。

查看更多

undefined

1. Boost.Test

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
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <stdexcept>

void test(int n) {
if (n == 42) {
return ;
}
throw std::runtime_error("Not the answer");
}

BOOST_AUTO_TEST_CASE(my_test) {
BOOST_TEST_MESSAGE("Testing");
BOOST_TEST(1+1 == 2);
BOOST_CHECK_THROW(test(41), std::runtime_error);
BOOST_CHECK_NO_THROW(test(42));

int expected = 5;
BOOST_TEST(2+2 == expected);
BOOST_CHECK(2+2 == expected);
BOOST_REQUIRE(1+1 == 3);
BOOST_TEST_MESSAGE("no execute");
}

BOOST_AUTO_TEST_CASE(null_test) {}

编译:GCC:g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework

  • 我们在包含单元测试的头文件之前定义了 BOOST_TEST_MAIN。如果编译时用到了多个源文件,只有一个应该定义该宏。多文件测试的时候,我一般会考虑把这个定义这个宏加包含放在一个单独的文件里(只有两行)

查看更多

undefined

基于 thread 的多线程开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class scoped_thread {
public:
template<typename... Arg>
explicit scoped_thread(Arg&&... arg) : thread_(std::forward<Arg>(arg)...) {}
scoped_thread(scoped_thread&& other) noexcept : thread_(std::move(other.thread_)) {}
scoped_thread(const scoped_thread&) = delete;
~scoped_thread() {
if (thread_.joinable()) {
thread_.join();
}
}

private:
std::thread thread_;
};
  1. 我们使用了可变模板和完美转发来构造 thread 对象。
  2. thread 不能拷贝,但可以移动;我们也类似地实现了移动构造函数。
查看更多

undefined

异常安全:指当异常发生时,既不会发生资源泄漏,系统也不会处于一个不一致的状态

异常的问题

  1. 异常违反了”你不用就不需要付出代价”的C++原则。只要开启了异常,即使不使用异常你编译出的二进制代码通常也会膨胀

    目前主流的异常实现中,都倾向于牺牲可执行文件大小、提供主流程的性能。

查看更多

undefined

一、智能指针

auto_ptr:拷贝时转移指针的所有权

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template <typename T>
class smart_ptr {
smart_ptr (smart_ptr& other) {
ptr_ = other.release();
}
smart_ptr& operator=(smart_ptr& rhs) {
smart_ptr(rhs).swap(*this);
return *this;
}
T* release() {
T* ptr = ptr_;
ptr_ = nullptr;
return ptr;
}
void swap(smart_ptr& rhs) {
using std::swap;
swap(ptr_, rhs.ptr_);
}
};

上述代码中这种惯用法保证了强异常安全性:赋值分为拷贝构造和交换两步,异常只可能在第一步发生;而第一步如果发生异常的话,this 对象完全不受任何影响。无论拷贝构造成功与否,结果只有赋值成功和赋值没有效果两种状态,而不会发生因为赋值破坏了当前对象这种场景。

不过 auto_ptr 将它传递给另一个对象之后,就不再拥有这个对象了。

unique_ptr:移动指针

1
2
3
4
5
6
7
8
9
10
template <typename T> 
class smart_ptr {
smart_ptr (smart_ptr&& other) {
ptr_ = other.release();
}
smart_ptr& operator=(smart_ptr&& rhs) {
rhs.swap(*this);
return *this;
}
};

查看更多