栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

新工作一些基础知识

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

新工作一些基础知识

YAML

YAML 入门教程 | 菜鸟教程YAML 是 'YAML Ain't a Markup Language'(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:'Yet Another Markup Language'(仍是一种标记语言)。 YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数..https://www.runoob.com/w3cnote/yaml-intro.html

ISO 8601

​​​​​​了解一下ISO 8601是什么了解一下ISO 8601是什么https://mp.weixin.qq.com/s?src=https://www.mshxw.com/skin/sinaskin/image/nopic.gif> ROBIN_SET

robin-map:快速hash_map和hash_set - 知乎

robin-map是用c++写的快速hash map 和 hash set,提供快速的插入、查找和删除操作。

Key Features

  1. 仅头文件
  2. 速度快
  3. 高效序列化
  4. API类似std::unordered_map和std::unordered_set
  5. MIT license

boost::noncopyable,

class please_dont_make_copies : boost::noncopyable {};

int main() {
please_dont_make_copies d1;
please_dont_make_copies d2(d1);
please_dont_make_copies d3;
d3=d1;
}

这个例子不能通过编译。由于noncopyable的复制构造函数是私有的,因此对d2进行复制构造的尝试会失败。同样,由于noncopyable的赋值操作符也是私有的,因此将d1赋值给d3的尝试也会失败。

UT,IT,ST,UAT

UT,IT,ST,UAT指单元测试,集成测试,系统测试 ,用户接受测试。

CI 是什么?CI 和 CD 有什么区别?

缩略词 CI / CD 具有几个不同的含义。CI/CD 中的“CI”始终指持续集成,它属于开发人员的自动化流程。成功的 CI 意味着应用代码的新更改会定期构建、测试并合并到共享存储库中。该解决方案可以解决在一次开发中有太多应用分支,从而导致相互冲突的问题。

CI/CD 中的“CD”指的是持续交付和/或持续部署,这些相关概念有时会交叉使用。两者都事关管道后续阶段的自动化,但它们有时也会单独使用,用于说明自动化程度

具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。这些关联的事务通常被统称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。

_access

win:int _access(char* path,int mode)

gnu:access

头文件
功能:确定文件或文件夹的访问权限。如果指定的存取方式有效,则函数返回0,否则函数返回-1。
参数path 是访问文件所在的路径名,mode是访问判断模式,
具体含义如下:
  R_OK 只判断是否有读权限
  W_OK 只判断是否有写权限
  X_OK 判断是否有执行权限
  F_OK 只判断是否存在

之前也使用过fopen判断文件是否存在,但_access函数更为方便。

eg:

nFileExit = _access(strnew.c_str(),0);
if(nFileExit == 0)
{
    CopyFile(strfilename.c_str(), strnew.c_str(), 0);
} 
else
{

}

GetPrivateProfileString
GetPrivateProfileString(lpszSection, lpszKey, lpszDefault, lpszReturnBuffer, cchReturnBuffer, lpszFile)
lpszSection: ini文件中小节的名称,格式[name]

lpszKey:  条目名称

lpszDefault: 当没有读取到对应条目值时,以此值返回, 一般设为NULL

lpszReturnBuffer: 存放所读取的空间

lpszfile: ini 文件绝对名称

#include 
#include 
#include 


using namespace std;


char    IP_addr[128] = {''};
char    IP_addr_1[128] = {''};

int main(int argc, char *argv[])
{
    cout << g_IP_addr_1<<" here is IP_addr_1"< 

INI文件:

[TESTER_SETUP]
IP_ADDRESS_1= 192.168.100.254

————————————————

fetch_add() fetch_sub()

对一个数进行原子操作 +1  -1,一般用在引用计数中、;

内联函数和宏定义

:当编译器发现某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数的代码,整段插入到当前位置。这样做的好处是省去了调用的过程,加快程序运行速度。(函数的调用过程,由于有前面所说的参数入栈等操作,所以总要多占用一些时间)。这样做的不好处:由于每当代码调用到内联函数,就需要在调用处直接插入一段该函数的代码,所以程序的体积将增大

1、内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快。

2、内联函数可以调试,而宏定义是不可以调试的。
内联函数与宏本质上是两个不同的概念如果程序编写者对于既要求快速,又要求可读的情况下,则应该将函数冠以inline。下面详细介绍一下探讨一下内联函数与宏定义

a、内联函数编译时要做类型检查,而后在将代码在函数调用点展开;而宏定义是在代码处不做任何检查的简单替换,从这点来看,内联函数更为安全。
b、inline函数是函数,但在编译时不单独产生代码,而是将有关代码嵌入到调用处;而宏定义不是一个函数只是在编译预处理阶段将有关字符串替换成宏体
————————————————

与C++11多线程相关的头文件

C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是< atomic> ,< thread>,< mutex>,< condition_variable>和< future>。 

线程 使用线程类,更加优秀的跨平台

互斥量和锁 同样优秀的跨平台。

std:: thread

C++——多线程编程(一)std::thread_linyyy的博客-CSDN博客

std::ref函数_Ch_zaqdt的博客-CSDN博客_std::ref的作用

     C++11 的std::ref函数就是为了解决在线程的创建中等过程的值拷贝问题,下面将会用一个线程的创建来展示ref函数的作用。

 因为fun函数中的对象和主函数中的对象所在的内存地址不同,所以如果我们想在fun函数中对这个对象进行值的修改的时候在main中就不会起作用,这就失去了引用的一个作用

    可以看到参数传递的过程中没有调用拷贝构造函数,而且内存地址相同,更改的值也达到了我们想要的效果,但是为了保证线程的安全,这样的方式不可以用detach使主线程与子线程分开。

 join()方法的作用就是让主线程等待子线程执行结束之后再运行主线程

mutable 有什么用?如果我想在常成员函数内部,修改对象的某个成员变量时,怎么办?这时,就需要 引入 mutable,将该对象的成员变量定义为 mutable 变量,但是,我们会把定义为mutable的这个变量,看做不属于对象的状态。这样,即使在常成员函数内部,mutable变量也可以被修改,与此同时,常成员函数内部,对于对象的其他成员变量(即对象的内部状态)还是不能修改的
————————————————

mutex和recursive_mutex void lock()

mutex使用锁有三种情况,

1、任何线程都没有使用mutex, 则调用的线程使用mutex

2、有其他线程使用mutex,当前调用的线程会阻塞,直到其他使用锁的线程锁释放

3、如果mutex被同一线程调用,会产生死锁

recursive_mutex和mutex类似,如果没有线程使用,则上锁

如果有线程使用,则阻塞

如果同一线程使用mutex,则添加新一层mutex,对应的释放时,需要多一次unlock()

std::this_thread::sleep_for

阻塞当前线程执行,至少经过指定的 sleep_duration。

此函数可能阻塞长于 sleep_duration,因为调度或资源争议延迟。

标准库建议用稳定时钟度量时长。若实现用系统时间代替,则等待时间亦可能对时钟调节敏感

lock_guard

相比于mutex功能,lock_guard具有创建时加锁,析构时解锁的功能,类似于智能指针,为了防止在线程使用mutex加锁后异常退出导致死锁的问题,建议使用lock_guard代替mutex。下面利用代码演示功能:

lock_guard具有两种构造方法:

  1. lock_guard(mutex& m)
  2. lock_guard(mutex& m, adopt_lock)

其中mutex& m是互斥量,参数adopt_lock表示假定调用线程已经获得互斥体所有权并对其进行管理了,因为构造时候会自动枷锁,所以adopt_lock其实就是告诉这个锁已经提前加过了。

想起了于哥写的自动的成员变量锁

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

// 时间模拟消息
string mock_msg()
{
	char buff[30] = { 0 };
	static int i = 100000;
	sprintf_s(buff, "%d", i--);
	return buff;
}

class CMutexTest
{
public:
	void recv_msg(); //接收消息
	void read_msg(); //处理消息
private:
	vector msg_queue; //消息队列
	mutex m_mutex;	//互斥量
};

// 模拟接收消息
void CMutexTest::recv_msg()
{
	while (true)
	{
		string msg = mock_msg();
		cout << "recv the msg " << msg << endl;

		// 使用"{ }"限定lock_guard作用域
		{
			lock_guard mylockguard(m_mutex);	
			// 消息添加到队列
			msg_queue.push_back(msg);
		}
		this_thread::sleep_for(chrono::milliseconds(10));//方便观察数据
	}
}

// 模拟读取处理
void CMutexTest::read_msg()
{
	while (true)
	{
		// 已经加锁
		m_mutex.lock();
		// 传递所有权给lock_guard,并传入adopt_lock表示已获得所有权
		lock_guard mylockguard(m_mutex, std::adopt_lock);
		if (!msg_queue.empty())
		{
			// 处理消息并移除
			string msg = msg_queue.front();
			cout << "read the msg " << msg << endl;
			msg_queue.erase(msg_queue.begin());
		}
		this_thread::sleep_for(chrono::milliseconds(15));//方便观察数据
	}
}

int main()
{
	CMutexTest my_test;
	thread recv_thread(&CMutexTest::recv_msg, &my_test); //接收线程
	thread read_thread(&CMutexTest::read_msg, &my_test); //处理线程

	recv_thread.join();
	read_thread.join();
}
unique_lock取代lock_guard


unique_lock是个类模板,工作中,一般lock_guard(推荐使用);lock_guard取代了mutex的lock()和unlock();

unique_lock比lock_guard灵活很多,效率上差一点,内存占用多一点。
C++11多线程 unique_lock详解_u012507022的博客-CSDN博客_c++ unique_lock

void inMsgRecvQueue()
	{
		for (int i = 0; i < 10000; i++)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
			std::unique_lock sbguard(my_mutex, std::defer_lock);//没有加锁的my_mutex
			sbguard.lock();//咱们不用自己unlock
			//处理共享代码
 
		    //因为有一些非共享代码要处理
			sbguard.unlock();
			//处理非共享代码要处理。。。
 
			sbguard.lock();
			//处理共享代码
 
			msgRecvQueue.push_back(i);
			//...
			//其他处理代码
			sbguard.unlock();//画蛇添足,但也可以
		}
	}

unique_lock所有权的传递
std::unique_lock sbguard(my_mutex);//所有权概念

sbguard拥有my_mutex的所有权;sbguard可以把自己对mutex(my_mutex)的所有权转移给其他的unique_lock对象;

所以unique_lock对象这个mutex的所有权是可以转移,但是不能复制。

方法1 :std::move()

方法2:return std:: unique_lock  代码如下:

std::unique_lock sbguard2(std::move(sbguard));//移动语义,现在先当与sbguard2与my_mutex绑定到一起了
 
//现在sbguard1指向空,sbguard2指向了my_mutex


std::unique_lock rtn_unique_lock()
	{
		std::unique_lock tmpguard(my_mutex);
		return tmpguard;//从函数中返回一个局部的unique_lock对象是可以的。三章十四节讲解过移动构造函数。
		//返回这种举报对象tmpguard会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数
	}
 
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 10000; i++)
		{
			std::unique_lock sbguard1 = rtn_unique_lock();
 
			msgRecvQueue.push_back(i);
		}
	}

总结一下,就是lock_guard 配合 adopt_lock使用,unique_lock配合 defer_lock使用。在两种情况都能使用时,推荐使用lock_guard,因为它更快并且使用的内存空间更少。unique_lock支持所有权的传递,所以更加灵活。
————————————————
版权声明:本文为CSDN博主「u012507022」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012507022/article/details/85909567

condition_variable

当 std::condition_variable对象的某个wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

std::condition_variable 对象通常使用 std::unique_lock 来等待,如果需要使用另外的 lockable 类型,可以使用std::condition_variable_any类,本文后面会讲到 std::condition_variable_any 的用法。

std::condition_variable::notify_one() 介绍

唤醒某个等待(wait)线程。如果当前没有等待线程,则该函数什么也不做,如果同时存在多个等待线程,则唤醒某个线程是不确定的(unspecified)。

std::condition_variable_any 介绍

与 std::condition_variable类似,只不过std::condition_variable_any的 wait 函数可以接受任何 lockable参数,而 std::condition_variable只能接受 std::unique_lock类型的参数,除此以外,和std::condition_variable几乎完全一样。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/913387.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号