文章目录
- 内存检测
- ProtoBuf
- CMake、vscode、clion、Qt
- 右值
- 1、临时变量右值引用
- 2、右值引用本质
- 函数返回
- std::function
- POD(Plain Old Data)
- thread_local
- new / delete
- 1、定位new运算符
- 可变参数模板
- typename和class
- 1、C++模板类头文件和实现文件分离的方法
- 2、函数显示实例化
- 3、类显示实例化
- 存储持续性、作用域和链接性
- 1、const、volatile、mutable
- 2、语言链接性
- 3、Linux下so库的符号可见性
- 友元与操作符重载
- operator (转换函数、操作符重载、User-defined literals)
- 继承与多重继承
- RTTI
- pair 和 tuple(元组)
- 智能指针
- constexpr
- C++ 原始字符串
- 异常
内存检测
valgrind简介与使用_WuYuJun’s blog的博客
Clang Sanitizers编译器自带的调试神器sanitizers - 知乎
clang自己的一些sanitizer,可以借鉴_去级得骨灰的博客
C++内存泄漏、数组越界……检测工具:Sanitizers_Owl丶的博客
ProtoBuf
GitHub - protocolbuffers/protobuf: Protocol Buffers - Google’s data interchange format
Protobuf 详解_Vic_Hao的博客
protobuf详解 - 知乎深入 ProtoBuf - 编码 - 简书
CMake、vscode、clion、Qt
VSCode 和 CLion 探索
一文搞懂如何在CMake中使用Qt_Copperxcx
CMake 教程Cmake官方教程解析
右值
左值引用和右值引用_陆尔尔的博客
C/C++学习记录:std::move 源码分析_河边小咸鱼的博客
1、临时变量右值引用
左值引用和右值引用都可以把临时对象的生命周期延长到与引用自身的生命周期相同。
说到实现,其实是变量替换,临时变量直接被构建在引用变量的位置,生命周期自然相同了。
T f() {
return T{};
}
T&& a= f();
//a继续有效
被编译器看成
void f(T& temp){
temp = ... 直接构造,不会走复制或移动构造函数
}
T a;
f(a);
//a继续有效。
2、右值引用本质
看不出右值引用对普通基本数据有任何实际意义,但是大量文章使用基本数据来讲解,完全没有讲到有意义的点子上,这样过于简化讲解,容易误导、困惑初学者。右值引用真正用意,是用于解决类对象内部拥有的动态数据的回收(转移),提高程序运行效率。普通数据对右值引用的适用,仅仅是个副产品。
我们再看一个移动构造函数的具体实现,方便大家理解move语义存在的价值:
class MyVector {
int* data_;
size_t size_;
public:
MyVector(): size_(100) {
data_ = new int[size_];
}
~MyVector() {
delete[] data_;
}
MyVector(const MyVector& my_vector) { // Copy constructor
size_ = my_vector.size_;
data_ = new int[size_];
std::copy(my_vector.data_, my_vector.data_ + my_vector.size_, data_);
}
MyVector(MyVector&& my_vector) { // Move constructor
size_ = my_vector.size_;
data_ = my_vector.data_;
my_vector.size_ = 0;
my_vector.data_ = nullptr;
}
// Should define copy assignment operator here
// Should define move assignment operator here
};
MyVector my_vector;
MyVector my_vector1 = my_vector; // my_vector is lvalue, thus copy constructor is invoked.
MyVector my_vector2 = std::move(my_vector); // std::move(my_vector) is rvalue, thus move constructor is invoked.
这里,我们实现了一个简单的数组类,自定义了拷贝构造函数和移动构造函数。在拷贝构造函数中,把旧 data_ 数组中的每个元素依次赋值到新的对象中。在移动构造函数中,直接把旧 data_ 数组的指针赋值给新对象,从而避免了数据的拷贝。但移动后,需要把旧对象的 size_ 标记为 0,把 data_ 指针置空,以表示所有权的转移。这个简单的例子揭示了移动语义存在的价值,因为有些情况下,数据是可以转移所有权的,而不必拷贝一份。
函数返回
C++函数返回值作为左值问题 - Mr.南柯 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园
C++primer第五版 函数返回左值_elma_tww的博客
c++ 函数返回引用_keyouan2008的博客-
函数返回值的优化技术(RVO和右值引用)_werflychen的博客
返回值和右值引用的传递问题_章志强的博客
C++函数的返回类型声明为一个右值引用类型,会发生什么事情?
char &change_value(string &str, int n) {
return str[n];
}
std::function
std::function详解_在座的各位都是高手的博客
std::function详解_A 壹零贰肆的博客
POD(Plain Old Data)
C++中的POD类型_柚子树cc的博客
podc++中的POD类型 - 柳刚 -
thread_local
c++11: thread_local_zzhongcy的博客
new / delete
C/C++——new和delete的实现原理(详解)__BitterSweet的博客
VS 反汇编方法及常用汇编指令介绍_超自然祈祷的博客
1、定位new运算符
C++ 定位new运算符_Timplan的博客
定位new运算符_努力的小带土的博客
可变参数模板
可变参数模板(C++11)_tony__lin的博客-
typename和class
关于C++中模板中的typename和class的区别比较 - 百度文库
C++模板详解(一) - 百度文库
C++模板之typename和class关键字的区别 - CTHON
C++函数模板及其实例化和具体化_Morning_Glory_JR的博客
C++11函数模板的默认模板参数 - 云+社区 - 腾讯云
C++模板特化与偏特化 - 云+社区 - 腾讯云
template<typename T,typename U=double>
void testTemplateFunc(T t=0,U u=0) {
cout<<"t="<<t<<" u="<<u<<endl;
}
// ================================================================
//函数模板
template<typename T, class N> void compare(T num1, N num2)
{
cout << "standard function template" << endl;
if(num1>num2)
cout << "num1:" << num1 << " > num2:" << num2 <<endl;
else
cout << "num1:" << num1 << " <= num2:" << num2 << endl;
}
//对部分模板参数进行特化
template<class N> void compare(int num1, N num2)
{
cout<< "partitial specialization" <<endl;
if (num1>num2)
cout << "num1:" << num1 << " > num2:" << num2 << endl;
else
cout << "num1:" << num1 << " <= num2:" << num2 << endl;
}
//将模板参数特化为指针
template<typename T, class N> void compare(T* num1, N* num2)
{
cout << "new partitial specialization" << endl;
if (*num1>*num2)
cout << "num1:" << *num1 << " > num2:" << *num2 << endl;
else
cout << "num1:" << *num1 << " <= num2:" << *num2 << endl;
}
//将模板参数特化为另一个模板类
template<typename T, class N> void compare(std::vector<T>& vecLeft, std::vector<T>& vecRight)
{
cout << "to vector partitial specialization" << endl;
if (vecLeft.size()>vecRight.size())
cout << "vecLeft.size()" << vecLeft.size() << " > vecRight.size():" << vecRight.size() << endl;
else
cout << "vecLeft.size()" << vecLeft.size() << " <= vecRight.size():" << vecRight.size() << endl;
}
// ================================================================
//类模板
template<typename T, class N> class TestClass
{
public:
static bool comp(T num1, N num2)
{
cout <<"standard class template"<< endl;
return (num1<num2) ? true : false;
}
};
//对部分模板参数进行特化
template<class N> class TestClass<int, N>
{
public:
static bool comp(int num1, N num2)
{
cout << "partitial specialization" << endl;
return (num1<num2) ? true : false;
}
};
//将模板参数特化为指针
template<typename T, class N> class TestClass<T*, N*>
{
public:
static bool comp(T* num1, N* num2)
{
cout << "new partitial specialization" << endl;
return (*num1<*num2) ? true : false;
}
};
//将模板参数特化为另一个模板类
template<typename T, class N> class TestClass<vector<T>,vector<N>>
{
public:
static bool comp(const vector<T>& vecLeft, const vector<N>& vecRight)
{
cout << "to vector partitial specialization" << endl;
return (vecLeft.size()<vecRight.size()) ? true : false;
}
};
1、C++模板类头文件和实现文件分离的方法
// template_compile.h
template<class T>
class base {
public:
base() {};
~base() {};
T add_base(T x,T y);
};
// template_compile.cpp
#include "template_compile.h"
template<class T>
T base<T>::add_base(T x,T y) {
return x+y;
}
// 在使用模板的测试文件use_template.cpp中:使用#include "template_compile.cpp"
#include<iostream>
#include "template_compile.cpp"
using namespace std;
void main()
{
base<int> bobj;
cout<<bobj.add_base(2,3)<<endl;
}
在使用模板的测试文件 use_template.cpp 中:使用 #include “template_compile.cpp”
或者把模块定义和实现都放在头文件中
【C++】类模板分离式写法_ainu412的博客
C++模板(函数模板/类模板)_普通网友的博客
2、函数显示实例化
#include <iostream>
using namespace std;
template <typename T> void func(T t) {
cout << t << endl;
}
// 函数模板显示实例化
// template [函数返回类型][函数模板名]<实际类型列表>(函数参数列表)
template void func<int>(const int&);
3、类显示实例化
#include <iostream>
using namespace std;
template <typename T> class A {
T num;
public:
A() {num = T(6.6);}
void print() {
cout << "A num:" << num << endl;
}
}
//类模板的显示实例化
//template class [类模板名]<实际类型列表>
template class A<int>;
存储持续性、作用域和链接性
9.2.5 静态持续性、内部链接性_落雪snowflake的博客
1、const、volatile、mutable
语言链接性:
extern "C" void spiff(int);
extern void spiff(int);
extern "C++" void spiff(int);
2、语言链接性
3、Linux下so库的符号可见性
Linux下so库的符号可见性: 解决多个库同名符号冲突问题_glemo的博客
友元与操作符重载
C++友元函数和友元类(C++friend)详解 - 百度文库
运算符重载的非成员函数形式_Jaihk662的博客
C++知识积累:成员函数运算符重载与非成员函数运算符重载_HerofH_的博客
operator (转换函数、操作符重载、User-defined literals)
C++转换函数 (conversion function)_万里归来少年心的博客
c++重载操作符operator的用法_炎芯随笔的博客
【c++】由构建复数类简析c++的user defined literal特性_ChillPolaris的博客
User-defined literals (since C++11) - cppreference.comC++ User-defined literals - 知乎
继承与多重继承
继承与派生(Part Ⅲ)——多重继承 & 虚基类_—Miss. Z—的博客
虚基类(多重继承)_GoodLinGL的博客
RTTI
C++ RTTI详解_彼 方的博客
pair 和 tuple(元组)
C++ pair的用法_&Mr.Gong的博客
c++ pair详解_lwgkzl的博客
C++中的tuple(元组)_奋斗的小菜鸟!的博客
智能指针
C++智能指针详解:shared_ptr_吃素的施子的博客
C++ shared_ptr用法、简析、案例_ve2102388688的博客
C++ weak_ptr_L7256的博客
C++智能指针weak_ptr详解_物随心转的博客
C++智能指针unique_ptr 详解_物随心转的博客
C++简单实现unique_ptr_吃米饭的博客
【Qt】Qt中智能指针_iriczhao的博客
constexpr
C++之constexpr详解_云洞的博客
C++ const 和 constexpr 的区别? - 知乎C++11/14 constexpr 用法 - 简书
C++ 原始字符串
C++ 原始字符串_Niklaus9084的博客
异常
C++的throw抛出异常机制