文章目录
1.引用和右值引用区别是什么?
- 一般认为,可以放在等号"="左边的是左值,可以放在等号右边的是右值。但是这个说法是错误的。
- 右值包括纯右值和将亡值。纯右值,比如常量,表达式值a+b;将亡值,比如函数传值返回,表达式的中间结果。顾名思义,将亡值的空间马上就要被释放了。
- 左值一般是可以修改的值,可以取地址的,通常是变量。
- 引用,只能引用左值,不能引用右值。但是const引用既可以引用左值,又可以引用右值。
int main(){
//a为左值,10为右值
int a = 10;
int& ra1 = a;
const int& ra2 = a;
//int& ra3 = 10;//编译错误,10为右值
const int& ra3 = 10;
return 0;
- 右值引用只能引用右值,不能引用左值。但是右值引用可以引用move之后的左值。因为move改变了左值的属性,变成了右值。
2.std::move和std::forward各有什么作用?
std::move
std::move用于将一个左值强制转换为右值引用,从而实现移动语义。移动语义可以避免在对象拷贝时发生内存分配和复制,提高程序运行效率。例如:
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = std::move(vec1); //将vec1的内容移动到vec2中
std::forward
std::forward用于实现完美转发,即在函数模板中将参数按原样转发给另一个函数。完美转发可以避免出现不必要的对象拷贝和移动,提高程序效率。例如:
template<typename T>
void func(T&& arg)
{
other_func(std::forward<T>(arg));
}
在此例中,如果arg是左值引用,则会转发为左值引用,如果arg是右值引用,则会转发为右值引用。这样可以保证在调用other_func时,参数类型和传递方式与原始函数调用保持一致,避免不必要的对象拷贝和移动。
3.c++中多线程同步有哪些方案?
1.互斥锁
本质就是一个特殊的全局变量,拥有lock和unlock两种状态,unlock的互斥锁可以由某个线程获得,一旦获得,这个互斥锁会锁上变成lock状态,此后只有该线程由权力打开该锁,其他线程想要获得互斥锁,必须得到互斥锁再次被打开之后
2.条件变量
互斥量不是万能的,比如某个线程正在等待共享数据内某个条件出现,可
可能需要重复对数据对象加锁和解锁(轮询),但是这样轮询非常耗费时间和资源,
而且效率非常低,所以互斥锁不太适合这种情况
我们需要这样一种方法:当线程在等待满足某些条件时使线程进入睡眠状态,
一旦条件满足,就唤醒因等待满足特定条件而睡眠的线程
如果我们能够实现这样一种方法,程序的效率无疑会大大提高,而这种方法正是条件变量!
#include <iostream>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
using namespace std;
pthread_cond_t qready=PTHREAD_COND_INITIALIZER; //cond
pthread_mutex_t qlock=PTHREAD_MUTEX_INITIALIZER; //mutex
int x=10,y=20;
void *f1(void *arg)
{
cout<<"f1 start"<<endl;
pthread_mutex_lock(&qlock);
while(x<y)
{
pthread_cond_wait(&qready,&qlock);
}
pthread_mutex_unlock(&qlock);
sleep(3);
cout<<"f1 end"<<endl;
return 0;
}
void *f2(void *arg)
{
cout<<"f2 start"<<endl;
pthread_mutex_lock