首页 > 编程语言 >C++ 围炉札记

C++ 围炉札记

时间:2023-09-11 15:04:11浏览次数:54  
标签:C++ 博客 vector 札记 template 围炉 my 模板


C++ 围炉札记_开发语言



文章目录

  • 内存检测
  • 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 Home

valgrind简介与使用_WuYuJun’s blog的博客

内存检测王者之剑—valgrind - 知乎

Clang Sanitizers编译器自带的调试神器sanitizers - 知乎

clang自己的一些sanitizer,可以借鉴_去级得骨灰的博客

C++内存泄漏、数组越界……检测工具:Sanitizers_Owl丶的博客



ProtoBuf

深入 ProtoBuf - 简介 - 简书

GitHub - protocolbuffers/protobuf: Protocol Buffers - Google’s data interchange format

Protobuf 详解_Vic_Hao的博客

Protobuf的简单介绍、使用和分析_单飞的梦的博客

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的博客

C++11 thread_local用法 - 知乎


new / delete

C/C++——new和delete的实现原理(详解)__BitterSweet的博客

CC++中的new和delete的实现过程 - 百度文库

VS 反汇编方法及常用汇编指令介绍_超自然祈祷的博客

1、定位new运算符

C++定位new运算符 - 知乎

C++ 定位new运算符_Timplan的博客

定位new运算符_努力的小带土的博客


可变参数模板

可变参数模板(C++11)_tony__lin的博客-

C++可变参数模板 - 知乎


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++模板类头文件和实现文件分离的方法

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的博客

C++内部链接性和无链接性

1、const、volatile、mutable

C++ 围炉札记_开发语言_02


C++ 围炉札记_c++_03


C++ 围炉札记_知乎_04

语言链接性:

extern "C" void spiff(int);
extern void spiff(int);
extern "C++" void spiff(int);

2、语言链接性

C++ 围炉札记_c++_05


3、Linux下so库的符号可见性

Linux动态库同名函数处理原则 - 百度文库

Linux下so库的符号可见性: 解决多个库同名符号冲突问题_glemo的博客

linux 下同名符号冲突问题解决方案 | 函数


友元与操作符重载

C++友元函数和友元类(C++friend)详解 - 百度文库

运算符重载的非成员函数形式_Jaihk662的博客

C++运算符重载为非成员函数

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

constexpr究竟有什么用? - 知乎

C++之constexpr详解_云洞的博客

constexpr_傻月菇凉的博客

C++ const 和 constexpr 的区别? - 知乎C++11/14 constexpr 用法 - 简书


C++ 原始字符串

C++ 原始字符串_Niklaus9084的博客


异常

C++的throw抛出异常机制

C++ throw抛出异常用法详解



标签:C++,博客,vector,札记,template,围炉,my,模板
From: https://blog.51cto.com/u_15930680/7435958

相关文章

  • VC++ 知识小结(续)
    1)当文档被修改时,如何在标题上加上标志'*'?重载CDocument类的虚函数virtualSetModifiedFlag:voidCTest2Doc::SetModifiedFlag(BOOLbModified){CStringstrTitle=GetTitle();CStringstrDirtyFlag="*";//notespacebeforethe'*'......
  • 七、PCL&C++相关小知识
    1、智能指针初始化(pcl库)智能指针在用的时候一定要初始化①在函数里面进行初始化pcl::PointCloud<pcl::PointXYZ>::Ptrcloud_source(newpcl::PointCloud<pcl::PointXYZ>)这里的Ptr就是智能指针,所以只看到过cloud的创建部分,而通常没有cloud的delete部分。②在类里面初始化类内部初......
  • C++ STL之map、multimap
    map和multimap是C++STL(StandardTemplateLibrary)中的关联容器,它们提供键值对的存储和访问。map是一个有序关联容器,它存储一组键值对,其中每个键都是唯一的。map中的键值对按照键的升序排序。用户可以通过键来访问、修改和删除对应的值。map的实现通常使用平衡二叉搜索树(如红黑树......
  • C++的String与UF8互转
    UTF8_To_String#include<Stringapiset.h>#include<iostream>std::stringUTF8_To_String(conststd::string&str){intnwLen=MultiByteToWideChar(CP_UTF8,0,str.c_str(),-1,NULL,0);wchar_t*pwBuf=newwchar_t[nwLen+1];//一定要加......
  • c++程序设计语言
    把那些重要的东西适度地记录索引,但是一些不太重要的细节就在书上标记就行。[ch7]# void*指针的使用(149)/nullptr# 原始字符串;不同语言的大字符集(153)# 多维数组至少需要知道哪些边界大小值(160)#......
  • C++ virtual关键字
    用来修饰父类中的函数:1、修饰父类中的普通函数:1#include<iostream>2#include<string>3#include<stdlib.h>45usingnamespacestd;67classbase8{9public:10voidfun1(){cout<<"thisisbase::fun1"<<endl;}......
  • 18、复合类型之指针(P47、P48、P49、P50);C++ primer 2.3.2
    1、C++中的“声明符”是什么?声明符是用来指定变量或函数的类型、名称和属性的符号。例如:intlist[20]; 声明了一个名为list的整型数组,它有20个元素。int是类型说明符,list[20]是声明符char*cp; 声明了一个名为cp的指向字符的指针1。*cp是声明符doublefunc(void);......
  • c++中的数论知识
    写在开头:word的公式打不上来,只能截图了一.组合数学(1)加法定理与乘法原理加法原理:做一件事情,完成它可以有n类办法,在第一类办法中有m1种不同的方法,在第二类办法中有m2种不同的方法,……,在第n类办法中有mn种不同的方法。那么完成这件事共有N=m1+m2+…+mn种不同的方法。乘法原理:做一......
  • C++的运算符重载介绍
    所谓重载,就是赋予新的含义。函数重载(FunctionOverloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作。运算符重载(OperatorOverloading)也是一个道理,同一个运算符可以有不同的功能。实际上,我们已经在不知不觉中使用了运算符重载。例如,+号可以对不同类型(int、float等)的......
  • C++的知识
    首先,让我们了解一下C++是什么。C++是一种高级的面向对象编程语言,泰兰德幻,它是C语言的扩展。由于其高度的灵活性和强大的功能,C++在各种领域中得到了广泛的应用,尤其在游戏开发、系统编程和嵌入式设备等方面。C++的优势之一是其强大的数据类型系统。C++支持不同的数据类型,包括整数、......