C++ 基础相关 备忘

文章介绍了C++中的decltype用于获取变量的类型,编译选项-as-needed和--no-as-needed在链接动态库时的作用,strace工具如何跟踪程序执行,以及移动构造在减少拷贝构造上的效率优势。同时,列举了C++11的一些新特性,如std::forward_list,std::unordered_map,std::thread,std::atomic和条件变量等。
摘要由CSDN通过智能技术生成

一、decltype 获取类型

typeid(a).name()

int i = 0; decltype(i) j = 0; cout << typeid(j).name() << endl;

二、编译选项 -as-needed

  1. g++ -std=c++11 -o exe_main main.cpp 默认是 -as-needed 
  2. g++ -Wl,--no-as-needed -std=c++11 -o exe_main main.cpp
  3. g++ -std=c++11 -o exe_main main.cpp -lpthread 

上面3个编译之后执行崩溃报错:

terminate called after throwing an instance of 'std::system_error'
what(): Enable multithreading to use std::thread: Operation not permitted
Aborted

-as-needed 就是忽略链接时没有用到的动态库

--no-as-needed 就是不忽略链接时没有用到的动态库

g++ -Wl,--no-as-needed -std=c++11 -o exe_main main.cpp -lpthread 这样编译之后执行正确

三、strace 跟踪执行

root@ubuntu:/home/guohua# strace ./fftest
execve("./fftest", ["./fftest"], [/* 28 vars */]) = 0
brk(0)                                  = 0x237c000
access("/etc/ld.so.nohwcap", F_OK)      = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffd01a4c000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/tang/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/tang/lib", {st_mode=S_IFDIR|0755, st_size=24576, ...}) = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=78567, ...}) = 0
mmap(NULL, 78567, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffd01a38000
close(3)                                = 0

四、移动构造

A  a; //以下1只发生一次移动构造,比2少一次赋值构造和一次拷贝构造

  1. new A(std::move(a));// 只发生一次移动构造接管原来的a;
  2. A a1 = std::move(a); //发生一次移动构造,然后是赋值构造
    new A(a1);//拷贝构造

可见 new std::string(std::move(data)) 只发生一次移动拷贝,新的string接管原来string的data,不发生实际的数据拷贝,开销较小

void test_thread(){
A a;
//A a1 = std::move(a);
//new A(a1);
new A(std::move(a));
printf("begin put thread param A\n");
std::thread thread_ = std::thread([&](){
a.hello();
});
printf("end put thread param A\n");
thread_.join();
/*[=](){} lamda表达式传值,1次赋值拷贝,再是1次拷贝构造,2次移动构造
I'm A
begin put thread param A
I'm operator= A
I'm copy A
I'm move A
I'm move A
I'm ~A
hello A
I'm ~A
I'm ~A
end put thread param A
I'm ~A
*/

/*[&](){} lamda表达式传引用,没发生任何构造
I'm A
begin put thread param A
end put thread param A
hello A
I'm ~A
*/
}

五、C++11 一些新特性

1. std::forward_list

新增的线性表,与list区别在于它是单向链表。

std::forward_list<int> numbers = {1,2,3,4,5,4,4};
numbers.remove(4);

2. std::unordered_map

与std::map用法基本差不多,但STL在内部实现上有很大不同,std::map使用的数据结构为二叉树,而std::unordered_map内部是哈希表的实现方式,哈希map理论上查找效率为O(1)。但在存储效率上,哈希map需要增加哈希表的内存开销。

std::unordered_map<std::string, std::string> mymap = { { "house","maison" } };

unsigned n = mymap.bucket_count();

3. std::unordered_set

数据存储结构也是哈希表的方式结构,除此之外,std::unordered_set在插入时不会自动排序。

4. std::thread 线程对象

#include <thread>
std::thread t1(threadfun1);
std::thread t2(threadfun2, 10, "abc");
std::thread([=](){})
t.join();
t.detach();

5. std::atomic 原子操作

大括号初始化 std::atomic_bool is_valid_{ false };

6. std::condition_variable 条件变量

需要条件变量cv、锁和条件共同完成。

锁只是保护共享资源或者临界区互斥访问,访问完就失去保护。临界区是需要不断检测某个条件是否满足时,如果没有条件变量机制,那就需要不断的轮询检测,引入条件变量之后,在临界区检测条件不满足时挂起等待,等这个条件在另外一个线程触发满足时唤醒。类似于select机制,只是select监听的是fd,条件变量监听的是一般的条件。

#include <condition_variable>
std::condition_variable cv; // 对应 pthread_cond_t

离不开锁  std::mutex mtx; 使用的是 unique_lock

std::unique_lock<std::mutex> lck(mtx);//std::mutex对应pthread_mutex_t,unique_lock() 对应 pthread_mutex_lock();
cv.wait(lck);//{ cv不满足lck.unlock()解除对临界资源的锁定,把当前线程加入等待队列 pthread_cond_wait(cv),阻塞,唤醒之后lck.lock()继续锁定资源。cv.wait()对应pthread_cond_wait();

在子线程中需要对条件变量cv加锁之后调用wait阻塞着等待资源,如果wait的时候不传锁进去,那阻塞的时候锁就得不到释放,外面其他共用锁的地方就拿不到锁,所以把锁传进wait内部就是为了阻塞的时候释放锁给外面的线程使用,等阻塞结束(被唤醒)再继续锁上。这也是为啥cv选择 unique_lock 的原因,因为 unique_lock 提供了lock()和unlock()的操作。

std::unique_lock<std::mutex> lck(mtx);
cv.notify_all();//对应 pthread_cond_broadcast(),cv.notify()对应 pthread_cond_signal()。

7.std::function、std::bind

std::function 接受函数对象
void Add(std::function<int(int, int)> fun, int a, int b){
        int sum = fun(a, b);
        std::cout << "sum:" << sum << std::endl;
}
std::bind 可绑定全局函数,类函数

test.Add(std::bind(&TestAdd::Add, testAdd, std::placeholders::_1, std::placeholders::_2), 1, 2);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tangcpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值