C艹11以及开发经验

1.auto和decltype关键字

// 用auto告知编译器模板的返回类型需要自动推导
// 用decltype(expression)告知编译器返回类型根据expression推导
// -> decltype(expression) 这种表示法叫做尾置返回类型
template <typename T, typename U>
auto f(T t, U u) -> decltype(t + u)
{
return t + u;
}

// C++14
template <typename T, typename U>
decltype(auto) sum(T x, U y) // 根据return后面的表达式自动推断返回类型
{ // 注意这里是以decltype的类型推导规则来推断返回类型
return x + y;
}

2.完美转发
std::forward(x) //原来是啥类型的,经过forward之后就变成啥类型的
当模板参数为引用类型T、T&&时,返回右值引用;
当模板参数为引用类型T&时,返回左值引用。
将一个传进函数的参数原封不动的传递出去,(右值引用类型是独立于值的,一个右值引用参数作为函数的形参,
在函数内部再转发成改参数的时候就变成一个左值,并不是它原来的类型)

3.function
定义为:
std::function<int(int,int)> mod = [](int i, int j){return i % j; };
这里std::function<int(int,int)>的作用就类似于int和auto。

4.cbegin()和cend()决定返回的迭代器类型为const,防止对原有数据进行更改

5.数组指针定义:含有10个整数元素的数组
typedef int arrT[10]
using arrT=int[10]

6.尾置返回类型,针对任何函数
auto func(int i)->int(*)[10];//返回的是一个指针,该指针指向了含有10个整数的数组

7.constexpr构造函数

  1. emplace会再容器管理的内存中直接创建对象,而push_back会创建一个临时对象,再压入容器中

9.shrink_to_fit();//使得容器的Capacity与Size匹配.

10.固定搭配写法:
pid_t gettid()
{
return (pid_t)syscall(SYS_gettid);//返回线程id唯一标识
//或者写成 static_cast<pid_t>(syscall(SYS_gettid));
}

  1. epoll使用方法:
    (1) int efpd=epoll_create(int size);

(2) nRet=epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev); //

  1. 内存池
    开发原因:
    高并发时较小内存块使用时,系统调用频繁(malloc,free)降低系统执行效率;
    频繁使用时增加系统内存碎片,降低内存使用效率;
    无垃圾回收,容易造成内粗泄露,导致内存枯竭;

13.上行转换:把派生类的指针和引用转换成基类表示;
下行转换:把基类的指针和引用转换成派生类;

  1. promise通常与future配合使用,在一个线程中传入数据,在另一个线程中获取

1)std::future类模板,future对象提供访问异步操作结果的机制,很轻松解决从异步任务中返回结果。(方便获取结果)
a.std::async 函数会返回一个std::future
b.std::promise::get_future 调用成员函数,获取 std::future
c.std::packaged_task::get_future 调用成员函数,获取 std::future

std::future result = std::async({
std::this_thread::sleep_for(std::chrono::milliseconds(500));
return 8;
});//创建异步线程
std::cout << "the future result : " << result.get() << std::endl;//获取线程执行结果
std::cout << "the future status : " << result.valid() << std::endl;

#include <iostream>
#include <future>
#include <chrono>
 
void Thread_Fun1(std::promise<int> &p)
{
	//为了突出效果,可以使线程休眠5s
	std::this_thread::sleep_for(std::chrono::seconds(5));
 
	int iVal = 233;
	std::cout << "传入数据(int):" << iVal << std::endl;
 
	//传入数据iVal
	p.set_value(iVal);//可以传入函数:  p.set_value(std::bind(&函数,std::placeholders::_1));
}
 
void Thread_Fun2(std::future<int> &f)
{
	//阻塞函数,直到收到相关联的std::promise对象传入的数据
	auto iVal = f.get();		//iVal = 233   //或者获取函数,再执行iVal(100);
 
	std::cout << "收到数据(int):" << iVal << std::endl;
}
 
int main()
{
	//声明一个std::promise对象pr1,其保存的值类型为int
	std::promise<int> pr1;
	//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定
	std::future<int> fu1 = pr1.get_future();
 
	//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行
	std::thread t1(Thread_Fun1, std::ref(pr1));
	//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行
	std::thread t2(Thread_Fun2, std::ref(fu1));
 
	//阻塞至线程结束
	t1.join();
	t2.join();
 
	return 1;
}
  1. CMakeLists.txt写法总结

rm -rf * #表示删除当前目录

1)编译main.cpp
PROJECT(HELLO) # 指定工程名字
SET(SRC_LIST main.cpp) #显示指定变量 多个cpp文件的则:SET(SRC_LIST p1.cpp p2.cpp)
MESSAGE(STATUS “This is BINARY dir” ${HELLO_BINARY_DIR}) #向终端输出用户自定义的信息
MESSAGE(STATUS “This is SOURCE dir” ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST}) #生成可执行文件hello 源文件读取变量SRC_LIST内容 或者直接ADD_EXECUTABLE(hello ${hello main.cpp})

cmake . #表示在当前目录编译
./hello

  1. 变量使用${}取值,指令一般用大写字母

3) 上面的例子是内部构建,会产生许多临时文件,外部构建会把生成的临时文件放到build目录下,在build目录下运行make来构建工程

mkdir build
cd build/
cmake … #…表示上一级目录

  1. 存在目录
    (使用tree能够看到目录结构)

.
|–build
|–CMakeLists.txt
|–src
|–CMakeLists.txt
|–main.cpp

  1. Linux中C++基础
    1) .o 目标文件,相当于win的.obj
    .so 相当于win的dll
    .a 静态库
    *.inl 文件是内联函数的源文件,通常内联函数在C++头文件中实现,但有时为了考虑将其实现与头文件分离,
    故意在另一文件中实现,通常它在声明内联函数的头文件的末尾被#include语句包含进来。

  2. oprerator++(int){}//对i++重载
    operator++(){}//对++i重载

18.基础C库函数实现

//my_memcpy实现重叠内存转移
char* my_memcpy(char* _Dest, const char* _Source, int count)
{
    //检查传入参数的有效性
    assert(NULL != _Dest);
    assert(NULL != _Source);
    if (NULL ==_Dest || NULL == _Source)
         return NULL;
    char* ret = _Dest;
    /**
    _Dest和_Source的内存地址有三种排列组合:
    1. _Dest和_Source没有发生重叠;
    2. _Dest和_Source地址重叠,且_Dest的地址大于_Source的地址;
    3. _Dest和_Source地址重叠,_Dest的地址小于_Source的地址;
    第一种情况和第三种情况,直接从低位字节开始复制,即可;
    第二种情况,必须从高位字节开始复制,才能保证复制正确。
    */
    if (_Dest > _Source && _Dest < _Source + count )
    {
         _Dest = _Dest + count - 1;
         _Source = _Source + count - 1;
         while(count--)
         {
             *_Dest-- = *_Source--;
         }
    }else
    {
         while(count--)
         {
             *_Dest++ = *_Source++;
         }
    }
    return ret;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值