- //std::move的移动构造函数的简单使用;
#include
using namespace std;
int main()
{
std::string str(“hello”);
std::vectorstd::string strvec;
strvec.push_back(str);
cout<<str<<endl;
strvec.push_back(std::move(str)); //调用std::move移动构造函数,掏空str,掏空后,最好不要用str;
cout<<str<<endl; //输出为""
cout<<strvec[0]<<" "<<strvec[1]<<endl;
return 0;
}
2)函数模板的具体化应用案例;
#include
using namespace std;
void handle(int a)
{
cout<<"普通函数 "<<a<<endl;
}
template
void handle (T a)
{
cout<<"模板函数 "<<a<<endl;
}
template<>
void handle(double a)
{
cout<<"函数模板的具体化 "<<a<<endl;
}
int main()
{
handle(3);
handle(5);
handle(67.68);
return 0;
}
3)随机数的使用:
#include
#include <stdlib.h>
using namespace std;
int main()
{
srand((unsigned)time(0));
cout<<rand() % 10<<endl;
cout<<rand() % 10<<endl;
cout<<rand() % 10<<endl;
return 0;
}
4)设置输出精度的案例:
#include
#include
using namespace std;
int main()
{
cout<<cout.precision()<<endl; //返回当前精度值,默认输出6
cout.precision(12); //设置当前精度值
double a = 4.6644332211;
cout<<a<<endl;
return 0;
}
5)命名空间的使用
using Test::add; //打开包裹,拿出一个名称,叫做"声明";
using namespace Test; //打开包裹,拿出所有内容,叫做"指示";
//命名空间可以是不连续的,在头文件时,创建命名空间(创建包裹)
namespace Test
{
int add(int a,int b); //声明
}
namespace Test //有同名的命名空间,往包裹内部添加内容;
{
int add(int a,int b) //定义
{
return a + b;
}
}
int main()
{
cout<<Test::add(3,4)<<endl;
return 0;
}
6)重载new和delete操作符,内部利用的是malloc和free函数;
#include
#include
using namespace std;
void* operator new(size_t size)
{
cout<<"operator new : "<<size <<endl;
auto p = malloc(size);
if(!p)
{
throw std::bad_alloc();
}
return p;
}
void* operator new[](size_t size)
{
cout<<"operator new[] : "<<size <<endl;
auto p = malloc(size);
if(!p)
{
throw std::bad_alloc();
}
return p;
}
void operator delete(void* ptr)
{
cout<<“operator delete–”<<endl;
std::free(ptr);
}
void operator delete[](void* ptr)
{
cout<<“operator delete[]–”<<endl;
std::free(ptr);
}
class TestMem
{
public:
int a = 0;
TestMem()
{
cout<<“create memory–”<<endl;
}
~TestMem()
{
cout<<“decreate memory------”<<endl;
}
};
int main()
{
auto mem1 = new TestMem();
delete mem1;
int* arr1 = new int[1024];
delete[] arr1;auto mem2 = new TestMem[2];
delete[] mem2;return 0;
}
7)指针的应用
int* ptr = new int;
delete ptr;
ptr = nullptr; //没有这句话,如果再次执行delete ptr的话,会出现错误,如“free(): double free detected in tcache 2”
堆区和栈区是相对申请空间的,堆区是从低到高,栈区是从高到低;
8)不要在构造函数和析构函数中调用virtual函数,案例如下:
#include
#include
#include
using namespace std;
class Base
{
public:
Base(){sayHello(); }
virtual void sayHello()
{
cout<<“hello base constructor—”<<endl;
}
virtual void sayBye()
{
cout<<“sayBye base deconstructor—”<<endl;
}
~Base(){sayBye(); }
};
class Derived : public Base
{
public:
Derived(){}
void sayHello()override
{
cout<<“hello Derived constructor—”<<endl;
}
void sayBye()override
{
cout<<“sayBye Derived deconstructor—”<<endl;
}
};
int main()
{
Derived derived;
return 0;
}
输出情况:
hello base constructor—
sayBye base deconstructor—
9)条款10:operator=,operator+=等运算符重载,返回的是自身引用;
10)std::shared_ptr的用法:
shared_ptr myclone(int p)
{
// return new int§; //错误,隐式转换为shared_ptr
return shared_ptr(new int§); //必须显示的创建shared_ptr;
}
int main()
{
std::shared_ptr ptr = make_shared(42);
auto ptr1(ptr);
std::shared_ptr p5(new int(55));
return 0;
}
10)explicit在构造函数中的使用,代码如下:
class MyClass
{
public:
explicit MyClass(int num)
{
number=num;
}
private:
int number;
};
int main()
{
//如果构造函数中,添加关键字explicit,则下面这句代码是错误的,只能MyClass obj(10);
// MyClass obj=10; //ok, convert int to MyClass //做了隐式转换,实际是下面两句代码的执行过程;
// MyClass temp(10);
// MyClass obj = temp;
MyClass obj(10);
return 0;
}
11)详细的介绍delete[] 为什么里面不用写数字,代码如下:先转换为void**,再转换为size_t*;
int main()
{
std::string* ptr = new std::string[20];
using add_t = void*;
auto len = reinterpret_cast<size_t*>(reinterpret_cast<add_t*>(ptr) - 1);
cout<<"len: "<<*(len)<<endl;
delete[] ptr;
return 0;
}
12)非常清楚,在函数调用完成后,何时返回引用,何时返回值;
13)查看类型推导的结果
#include
#include
#include
#include
using namespace std;
template
void f(const T& param)
{
cout<<typeid(T).name()<<endl;
cout<<typeid(param).name()<<endl;
}
class Mywidget
{
};
std::vector createVec() //工厂模式
{
return {Mywidget{}};
}
int main()
{
const auto tmp = createVec();
if(!tmp.empty())
{
f(&tmp[0]);
}
return 0;
}
14)单例模式的简单应用1
#include
#include
#include
#include
using namespace std;
//单例模式三要素:定义私有构造函数,定义一个私有的静态实例,定义一个共有的获取实例的静态方法;
// (static静态成员数据) (static 静态成员函数)
class A
{
private:
A():m_name(“A”){cout<<“a constructor is handle”<<endl;}
~A(){ cout<<“a deconstructor is handle—”<<endl;}
A(const A& obj) = delete;
A& operator=(const A& obj) = delete;
static A* m_instance;
string m_name;
public:
static A* instance(void)
{
if(m_instance == nullptr)
{
m_instance = new A();
}
return m_instance;
}
void show(void)
{
cout<<m_name<<endl;
}
};
A* A::m_instance = nullptr; //静态数据
int main()
{
A::instance()->show();
return 0;
}
15)单例模式的模板类应用案例,包括了友元类的使用
#include
#include
using namespace std;
namespace Tool
{
template
class singleTon
{
public:
static T* instance()
{
if(instance_ == nullptr)
{
instance_ = new T();
}
return instance_;
}
private:
singleTon(){}
~singleTon(){}
singleTon(const singleTon& ) = delete;
singleTon& operator=(const singleTon)=delete;
private:
static T* instance_;
};
template
T* singleTon::instance_ = nullptr;
};
using namespace Tool;
class A
{
public:
friend class singleTon;
public:
void show(void)
{
cout<<m_name<<endl;
}
private:
A():m_name(“A”){cout<<“a constructor is handle”<<endl;}
~A(){ cout<<“a deconstructor is handle—”<<endl;}
A(const A& obj) = delete;
A& operator=(const A& obj) = delete;
private:
string m_name;
};
int main()
{
//单例模式在多线程安全访问的安全机制:在主线程创建,在子线程访问即可
using namespace Tool;
singleTon::instance(); //创建
singleTon::instance()->show(); //访问
return 0;
}
16)std::bind的参数绑定函数使用方法
int test(int a,int b,int c)
{
cout<<a<<b<<c<<endl;
return 0;
}
int main()
{
auto a = std::bind(test,1,2,3); //函数体和参数相绑定,成为一个新的函数体;
a();
return 0;
}
第二种写法:
int test(int a,int b,int c)
{
cout<<a<<b<<c<<endl;
return 0;
}
int main()
{
auto a = std::bind(test,1,std::placeholders::_1,std::placeholders::_2); //函数体和参数相绑定,成为一个新的函数体;
a(56,78);
return 0;
}
17)在C++中,using的三种使用方法:引入命名空间,定义类型别名,在派生类中引用基类成员;
using vectorType = std::vector; //用using定义类型别名
int main()
{
vectorType v1;
v1.push_back(23);
return 0;
}
(一)解压同事白晓明的env_sdk_2.4.1的sdk,把文件拷贝到如下docker(keen_meitner)文件夹下,注意拷贝到docker容器是跟目录,和原生的sdk不是一个目录!!!
docker cp env_sdk_2.4.1 keen_meitner:/
(二)进入keen_meitner docker容器:
docker exec -it keen_meitner /bin/bash
(三)在docker根目录下,find -name ti-cgt-c7000_2.0.1.STS,查找文件,输出结果如下:
./opt/autobrain/sysroot/toolschain/ti-cgt-c7000_2.0.1.STS
(四)更改编译选项:
1)在"vi tools/toolchain/toolchain_linux_a72.mk"文件下,更改TC_PATH_CC和TC_PATH_ROOTFS目录,如下所示(注意是toolschain):
TC_PATH_CC := /opt/autobrain/sysroot/toolschain/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin
TC_PATH_ROOTFS := /opt/autobrain/sysroot/toolschain/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc
2)在"vi tools/toolchain/toolchain_freertos_r5f.mk"文件下,更改TC_PATH_CC目录,如下所示(注意是toolschain):
TC_PATH_CC := /opt/autobrain/sysroot/toolschain/ti-cgt-armllvm_1.3.0.LTS
3)在"vi tools/toolchain/toolchain_freertos_c71.mk"文件下,更改TC_PATH_CC目录,如下所示(注意是toolschain):
TC_PATH_CC := /opt/autobrain/sysroot/toolschain/ti-cgt-c7000_2.0.1.STS
(五)在docker中,更改Makefile编译环境的方法:
1)进入/workspace/env_sdk_2.4.1/Libs目录下;
2)按ab_demo的编译格式更改,共计更改七处,如添加process17目标文件;
3)在/workspace/env_sdk_2.4.1/Libs目录下,输入make process17即可;
LIB-y += $(ROOTFS_DIR)/usr/lib64/libpthread.so
(六) 出现类似如“task.cpp:(.text._Z7AppRecvv+0x24c): undefined reference to `Osal_setCpuName’”的错误,是需要拷贝配置环境,方法如下:
用白晓明给的的那个环境拷贝:cp /workspace/env/cfg_env/scfg/buildcfg/process17/ /workspace/env_sdk_2.3.5/Libs/env/cfg_env/scfg/buildcfg -R
涂宁告诉的:cp env/cfg_env/scfg/buildcfg/ab_demo/ /env_sdk_2.4.1/Libs/env/cfg_env/scfg/buildcfg/ -R
(七)刘占山告诉的,需要添加编译配置文件,方法如下:
进入目录:“/workspace/env_sdk_2.3.5/Libs/env/cfg_env/scfg/buildcfg”,打开 vim scfg_buildlist.mk文件,添加如下语句:
SCFG_BUILD_LIST += process17.linux_a72.19^