C/C++使用指南
auto:for(auto& name : input){}
c++中name mingling较C更为复杂
创建静态链接库
gcc -fPIC -c a.c
gcc -fPIC -c b.c
gcc -shared -o libfoo.so a.o b.o
创建动态链接库
gcc -c a.c
gcc -c b.c
gcc -c main.c
ar cr libfoo.a a.o b.o
gcc main.o libfoo.a
链接:
-L [.] #添加搜索目录
-l[a] #链接liba.so
g++ -o temp ./main.so ./libb.so ./liba.so #首先查找libb,然后查找liba
alignas(64) int array[1024]; // 以64对齐内存
-l[lib]
选项需要在 cpp 文件后面(链接器从前向后处理,只从每个 lib 中提取当前需要的符号函数 见链接)-isystem [dir]
将 [dir]
指定为和系统 include,查找 include 顺序为 -I
目录,-isystem
目录,系统 include 目录
restrict关键字,告知编译器不存在指针aliasing
如:
void example2b(float * __restrict__ a, float * __restrict__ b, float * __restrict__ c) {
for (int i = 0; i < 1024; i++) {
a[i] = 0.0f;
b[i] = 0.0f;
for (int j = 0; j < 1024; j++) {
a[i] = a[i] + c[i<em>1024 + j];
b[i] = b[i] + c[i</em>1024 + j] * c[i*1024 + j];
}
}
}
告知编译器a,b,c三数组内容不重合
在cuda中,只有当指针标记为 const, restrict 时,cuda编译器才会认为数组为只读内容,并使用read-only cache对其优化
数组指针:int p[4]
: p为大小为4数组,其中每个元素为指向 int 指针。 [] 优先级高于 , 解析为 (int*) (p[4])
int (*p)[4]
: p为单个指针,指向 大小为 4 的 int 数组,初始化可以直接使用 p = new int8
宏定义:#define PRINTCLASS(ClassName) printout(#ClassName)
: #ClassName
传入参数转换为字符串 #define DeclareSomething(ArgumentName,i) int ArgumentName##i
: ##
用于连接两个单元#define Declare_Fun(...) typedef std::function<void(__VA_ARGS__)> iStdFunction
: ...
为可变参数,用 VA_ARGS
获取
gcc -E m.cpp -o m.i
: 预编译,m.i 为宏展开结果
编译与链接
-m
: x86 相关选项 -march=native
: 生成针对本机优化的代码-mcmodel=large
: 可以开超过 2G 的全局数组
include 文件在编译时直接使用对应文件替换 include 语句#include "filename"
首先在源文件路径搜索目标头文件,然后搜索默认路径#include <filename>
搜索默认路径
cpp : c pre-processor 负责头文件查找和替换cpp -v
显示头文件查找路径-Wl,param1,param2,...
: 编译时传给ld链接器的参数
c/c++ mocking function : -Wl,--wrap=[func]
对 func
进行 mock,调用 func
函数时会尝试调用 __wrap_func
,使用 __read_func
调用原 func
函数
C++ 模板相关
SFINAE (substitution-failure-is-not-an-error) 原则:在模板中执行替换时解析错误不认为是错误,而是忽略该模板
#include <iostream>
using namespace std;
void f(double a){
cout<<"in double f()"<<endl;
}
template<typename T>
void f(typename T::noexist a){
cout<<"in T::noexist f()"<<endl;
}
int main(){
f(1);
f(1.0);
}
此时 f(0)
和 f(1.0)
均调用 f(double a)
typename std::enable_if<(std::is_same<T, float>::value)>::type
当 T 为 float 时为 void type,否则解析失败
std::enable_if
定义:
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> {
typedef T type;
};
当条件为 true 时,enable_if
包括 typedef 成员 type
,等价于 T
。
在 C++11 中,当使用 std::enable_if
时,需要写 typename std::enable_if<...>::type
。
C++14 引入了 std::enable_if_t
,定义为:
template<bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;
可变模板参数
template <typename... TYPES>
void func(TYPES... vals) {
}
sizeof...(TYPES)
: 参数数量func1(vals...)
: 将可变参数传入函数
折叠表达式 (Fold expressions)
从 c++17 开始。
形如 (... && args)
展开为 (((arg1 && arg2) && arg3) && ...)
integer_sequence
定义为:
template< class T, T... Ints >
class integer_sequence;
一些 helper template :
特化下标为 size_t
情况:
template< std::size_t... Ints >
using index_sequence = std::integer_sequence<std::size_t, Ints...>;
构造 0
到 N-1
的下标序列:
template< class T, T N >
using make_integer_sequence = std::integer_sequence<T, /* a sequence 0, 1, 2, ..., N-1 */>;
template< std::size_t N >
using make_index_sequence = std::make_integer_sequence<std::size_t, N>;
构建与可变模板参数等长的序列:
template< class... T >
using index_sequence_for = std::make_index_sequence<sizeof...(T)>;
typename
用于在模板中表示一个东西是类型decltype
用于推导表达式的类型
template <typename T>
class MyClass {
public:
typename T::value_type member; // 'typename' specifies that T::value_type is a type
auto getMember() -> decltype(member) {
return member; // 'decltype' deduces the return type of the function based on 'member'
}
};
std::same
用于在编译时比较类型
if (std::is_same<typename DoCoul<PairStyle::COUL_FLAG>::type, CoulTag>::value) {
printf("ERROR: DoCoul<PairStyle::COUL_FLAG>::type is CoulTag\n");
exit(1);
}
template 推导数组大小
// From ABSL_ARRAYSIZE
#define PBRT_ARRAYSIZE(array) (sizeof(::pbrt::detail::ArraySizeHelper(array)))
namespace pbrt {
namespace detail {
template <typename T, uint64_t N>
auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
} // namespace detail
} // namespace pbrt