C++ std::thread使用

2023-05-16

c++ 11 之后有了标准的线程库:std::thread。通过c++11中的线程库创建线程,极为方便,且跨平台,是语言层面的。之前跨平台的多线程开发中,多使用boost 相关第三方库。

1.std::thread 构造函数

默认构造函数 		thread() noexcept;
初始化构造函数 	template <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args);
拷贝构造函数 [deleted] 	thread(const thread&) = delete;
Move 构造函数 	thread(thread&& x) noexcept;

(1).默认构造函数,创建一个空的 std::thread 执行对象。
(2).初始化构造函数,创建一个 std::thread 对象,该 std::thread 对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
(3).拷贝构造函数(被禁用),意味着 std::thread 对象不可拷贝构造。
(4).Move 构造函数,move 构造函数(move 语义是 C++11 新出现的概念,详见附录),调用成功之后 x 不代表任何 std::thread 执行对象。
注意:可被 joinable 的 std::thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached.

std::thread 各种构造函数例子如下:

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>

void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread " << n << " executing\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void f2(int& n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread 2 executing\n";
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main()
{
    int n = 0;
    std::thread t1; // t1 is not a thread,t1不是一个thread
    std::thread t2(f1, n + 1); // pass by value,按照值传递
    std::thread t3(f2, std::ref(n)); // pass by reference,引用
    std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread,t4执行t3,t3不是thread
    t2.join();
    t4.join();
    std::cout << "Final value of n is " << n << '\n';
}

2.std::thread 赋值操作

Move 赋值操作 	thread& operator=(thread&& rhs) noexcept;
拷贝赋值操作 [deleted] 	thread& operator=(const thread&) = delete; 

(1).Move 赋值操作(1),如果当前对象不可 joinable,需要传递一个右值引用(rhs)给 move 赋值操作;如果当前对象可被 joinable,则会调用 terminate() 报错。’
(2).拷贝赋值操作(2),被禁用,因此 std::thread 对象不可拷贝赋值。

请看下面的例子:

#include <stdio.h>
#include <stdlib.h>

#include <chrono>    // std::chrono::seconds
#include <iostream>  // std::cout
#include <thread>    // std::thread, std::this_thread::sleep_for

void thread_task(int n) {
    std::this_thread::sleep_for(std::chrono::seconds(n));
    std::cout << "hello thread "
        << std::this_thread::get_id()
        << " paused " << n << " seconds" << std::endl;
}

int main(int argc, const char *argv[])
{
    std::thread threads[5];
    std::cout << "Spawning 5 threads...\n";
    for (int i = 0; i < 5; i++) {
        threads[i] = std::thread(thread_task, i + 1);
    }
    std::cout << "Done spawning threads! Now wait for them to join\n";
    for (auto& t: threads) {
        t.join();
    }
    std::cout << "All threads joined.\n";

    return EXIT_SUCCESS;
}

3.其他成员函数

3.1 get_id()

获取线程 ID,返回一个类型为 std::thread::id 的对象。

请看下面例子:

//test.cpp
#include <iostream>
#include <thread>
#include <chrono> //该头文件详情可参考:https://www.cnblogs.com/jwk000/p/3560086.html

void foo()
{
  std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
  std::thread t1(foo);
  std::thread::id t1_id = t1.get_id();

  std::thread t2(foo);
  std::thread::id t2_id = t2.get_id();

  std::cout << "t1's id: " << t1_id << '\n';
  std::cout << "t2's id: " << t2_id << '\n';

  t1.join();
  t2.join();
  return 0;
}
//编译g++ -std=c++11 -pthread test.cpp -o test

从std::thread::id取得int值线程id

std::thread::id tid = std::this_thread::get_id();
_Thrd_t t = *(_Thrd_t*)(char*)&tid ;
unsigned int nId = t._Id

参考资料:https://www.cnblogs.com/yc-only-blog/p/9178935.html

3.2 joinable()

检查线程是否可被 join。检查当前的线程对象是否表示了一个活动的执行线程,由默认构造函数创建的线程是不能被 join 的。另外,如果某个线程 已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,因此也是可以被 join 的。

#include <iostream>
#include <thread>
#include <chrono>
 
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    std::thread t;
    std::cout << "before starting, joinable: " << std::boolalpha << t.joinable() << '\n';
 
    t = std::thread(foo);//此时子线程并不执行,在调json()或detach()后才执行
    std::cout << "after starting, joinable: " << t.joinable() << '\n';
 
    t.join();//说明:如果此处不调用join(),也不调用detach(),编译执行程序就会提示 terminate called without an active exception

    std::cout << "after joining, joinable: " << t.joinable() << '\n';
}
//join: Join 线程,调用该函数会阻塞当前线程,直到由 *this 所标示的线程执行完毕 join 才返回。

std::thread “terminate called without an active exception”请参考如下接:
https://www.cnblogs.com/little-ant/p/3312841.html

3.3 detach()

Detach 线程,将当前线程对象所代表的执行实例与该线程对象分离,使得线程的执行可以单独进行。一旦线程执行完毕,它所分配的资源将会被释放。

调用 detach 函数之后:

*this 不再代表任何的线程执行实例。
joinable() == false
get_id() == std::thread::id()

另外,如果出错或者 joinable() == false,则会抛出 std::system_error。

#include <iostream>
#include <chrono>
#include <thread>
 
void independentThread() 
{
    std::cout << "Starting concurrent thread.\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "Exiting concurrent thread.\n";
}
void threadCaller() 
{
    std::cout << "Starting thread caller.\n";
    std::thread t(independentThread);
    t.detach();
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Exiting thread caller.\n";
}
int main() 
{
    threadCaller();
    std::this_thread::sleep_for(std::chrono::seconds(5));
}

3.4 swap()

Swap 线程,交换两个线程对象所代表的底层句柄(underlying handles)。

#include <iostream>
#include <thread>
#include <chrono>
 
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
void bar()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    std::thread t1(foo);
    std::thread t2(bar);
 
    std::cout << "thread 1 id: " << t1.get_id() << std::endl;
    std::cout << "thread 2 id: " << t2.get_id() << std::endl;
 
    std::swap(t1, t2);
 
    std::cout << "after std::swap(t1, t2):" << std::endl;
    std::cout << "thread 1 id: " << t1.get_id() << std::endl;
    std::cout << "thread 2 id: " << t2.get_id() << std::endl;
 
    t1.swap(t2);
 
    std::cout << "after t1.swap(t2):" << std::endl;
    std::cout << "thread 1 id: " << t1.get_id() << std::endl;
    std::cout << "thread 2 id: " << t2.get_id() << std::endl;
 
    t1.join();
    t2.join();
}
执行结果如下:

thread 1 id: 1892
thread 2 id: 2584
after std::swap(t1, t2):
thread 1 id: 2584
thread 2 id: 1892
after t1.swap(t2):
thread 1 id: 1892
thread 2 id: 2584

3.5 native_handle

返回 native handle(由于 std::thread 的实现和操作系统相关,因此该函数返回与 std::thread 具体实现相关的线程句柄,例如在符合 Posix 标准的平台下(如 Unix/Linux)是 Pthread 库)。

3.6 hardware_concurrency [static]

检测硬件并发特性,返回当前平台的线程实现所支持的线程并发数目,但返回值仅仅只作为系统提示(hint)。

#include <iostream>
#include <thread>
 
int main() {
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << n << " concurrent threads are supported.\n";
}

4.std::this_thread 命名空间中相关辅助函数介绍

4.1 get_id()

获取线程 ID。

#include <iostream>
#include <thread>
#include <chrono>
 
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    std::thread t1(foo);
    std::thread::id t1_id = t1.get_id();
 
    std::thread t2(foo);
    std::thread::id t2_id = t2.get_id();
 
    std::cout << "t1's id: " << t1_id << '\n';
    std::cout << "t2's id: " << t2_id << '\n';
 
    t1.join();
    t2.join();
}

4.2 yield()

当前线程放弃执行,操作系统调度另一线程继续执行。

#include <iostream>
#include <chrono>
#include <thread>

// "busy sleep" while suggesting that other threads run 
// for a small amount of time
void little_sleep(std::chrono::microseconds us)
{
  auto start = std::chrono::high_resolution_clock::now();
  auto end = start + us;
  do {
      std::this_thread::yield();//让cpu执行其他空闲的线程
  } while (std::chrono::high_resolution_clock::now() < end);
}

int main()
{
  auto start = std::chrono::high_resolution_clock::now();

  little_sleep(std::chrono::microseconds(100));

  auto elapsed = std::chrono::high_resolution_clock::now() - start;
  std::cout << "waited for "
            << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
            << " microseconds\n";
}

4.3 sleep_until()

线程休眠至某个指定的时刻(time point),该线程才被重新唤醒。

template< class Clock, class Duration >
void sleep_until( const std::chrono::time_point<Clock,Duration>& sleep_time );

4.4 sleep_for()

线程休眠某个指定的时间片(time span),该线程才被重新唤醒,不过由于线程调度等原因,实际休眠时间可能比 sleep_duration 所表示的时间片更长。

#include <iostream>
#include <chrono>
#include <thread>

int main()
{
  std::cout << "Hello waiter" << std::endl;
  std::chrono::milliseconds dura( 2000 );
  std::this_thread::sleep_for( dura );
  std::cout << "Waited 2000 ms\n";
}

5.std::thread堆栈使用

#include <iostream>
#include <thread>
using namespace std;
void show()
{
	cout << "hello cplusplus!" << endl;
}
int main()
{
	//栈上
	thread t1(show);   //根据函数初始化执行
	thread t2(show);
	thread t3(show);
	t1.join();
	t2.join();
	t3.join();
	//线程数组
	thread threads[3]{thread(show), thread(show), thread(show)}; 
	for (auto& t: threads) 
	{ 
		t.join();
	}
	
	//堆上
	thread *pt1(new thread(show));
	thread *pt2(new thread(show));
	thread *pt3(new thread(show));
	pt1->join();
	pt2->join();
	pt3->join();
	//线程指针数
	thread *pthreads(new thread[3]{thread(show), thread(show), thread(show)});
	

	delete pt1;
	delete pt2;
	delete pt3;
	// delete [] pthreads;//这里直接delete会导致异常退出,因为线程没有join(),也没有detach()

	
	int threadNum = 3;
	thread* t = new thread[threadNum];
	if(t)
	{
		for ( int i = 0; i < threadNum; i++){
        	t[i] = thread(show);    
	    }

	    for ( int i = 0; i < threadNum; i++){
	        //t[i].detach(); //主进程不等子进程运行完
	        t[i].join();        //主进程等
	    }
	}
	delete [] t;
	return 0;
}

注意事项:
1.std::thread在栈内创建后,需要在同一个作用域内调用join() 或者 detach(), 否则退出作用域后,程序会异常退出, 具体原因如下

~thread()
{
	if (joinable())
		std::terminate();
}

其中的std::terminate()就是用来终止进程的调用。由于std::thread创建后默认是joinable的, 所以需要调用join()或者detach() 来使线程变成非joinable的状态, 具体使用join()还是detach() 取决于实际需求, 如果需要等待线程完成才能继续,那就使用join()来等待, 如果需要立刻返回继续其他操作, 那就调用detach()来脱离对线程的管理, 两者必须选一个。

2.调用new 创建的std::thread, 禁止直接使用delete, 需要在调用delete之前,调用 join()或者 detach() (如果创建线程后立刻调用了这两个函数中任意一个, 可以不再调用, 但是为了保险起见, 需要加上if(joinable()) 的判断), 原因见上一条。

6.std::thread 线程执行体

std::thread 执行体类似boost::thread, 并不要求是普通的函数,任何可调用的对象都可,具体接受下面四种:

  1. 普通函数
  2. 函数对象
  3. 类成员函数
  4. lambda 函数(匿名函数)
    分别使用举例如下:

(1) 普通函数

void hello() //不带参数 
{
	//do whatever you want 
} 
void hello(std::string name) //带参数 
{
	//do whatever you want using parameter in 
} 
std::thread thread1(hello); 
std::thread thread2(hello, "test");

(2) 函数对象

class Hello // 不带参数 
{
	public: Hello(){} 

	//over ride operator() 
	void operator()() const 
	{
		//do whatever you want
	} 
};

class Hello {
	public: Hello() {} 

	//over ride operator() 
	void operator()(const std::string name) const 
	{
		// do whatever you want using parameter in
	} 
};

std::thread thread3(Hello()); 
std::thread thread4(Hello(), "test");

(3) 类成员函数

class Hello {
	public: entity() 
	{
		// do whatever you want 
	} 

	//over ride operator() 
	void entity(const std::string name) 
	{
		// do whatever you want using parameter in name
	} 
};

Hello obj;
std::thread thread5(&Hello::entity, &obj);
std::thread thread6(&Hello::entity,  &obj, "test");
// std::thread thread5(&Hello::entity, this);
// std::thread thread6(&Hello::entity,  this, "test");

此种构造也可以借助std::bind使用另外一种方式:

std::thread  thread5(std::bind(&Hello::entity, &obj));
std::thread  thread6(std::bind(&Hello::entity,  &obj, "test"));

(4) lambda 函数

std::thread thread7([](T var1, T var2){ 
	//do whatever you want using parameter var1 var2
}, realValue1, readValue2);

//某匿名函数定义 
//auto fun = [](const char *str) {cout << str << endl; };

7.原子变量与线程安全

示例1:

#include <iostream>
#include <thread>
using namespace std;
const int N = 100000000;
int num = 0;
void run()
{
	for (int i = 0; i < N; i++)
	{
		num++;
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	thread t2(run);
	t1.join();//join之后开始执行子线程
	t2.join();//join之后开始执行子线程
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=100445432,用时 1013773 us
//注意linux下clock()单位是微妙,windows下clock()单位是毫秒

从上述代码执行的结果,发现结果并不是预计的200000000,这是由于线程之间发生冲突,从而导致结果不正确。为了解决此问题(多线程同时操作同一份数据),有以下方法:
(1)互斥量。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
const int N = 100000000;
int num = 0;
mutex m;
void run()
{
	for (int i = 0; i < N; i++)
	{
		m.lock();
		num++;
		m.unlock();
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	thread t2(run);
	t1.join();
	t2.join();
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=200000000,用时 40520541 us

通过互斥量后运算结果正确,但是计算速度很慢,原因主要是互斥量加解锁需要时间。
互斥量详细内容 请参考C++11 并发之std::mutex。
(2)原子变量。
例如:

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
const int N = 100000000;
atomic_int num{ 0 };//不会发生线程冲突,线程安全
void run()
{
	for (int i = 0; i < N; i++)
	{
		num++;
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	thread t2(run);
	t1.join();
	t2.join();
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=200000000,用时 7111836 us

通过原子变量后运算结果正确,计算速度一般。
(3)通过控制 join位置 。

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
const int N = 100000000;
int num = 0;
void run()
{
	for (int i = 0; i < N; i++)
	{
		num++;
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	t1.join();
	thread t2(run);
	t2.join();
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=200000000,用时 485837 us

运算结果正确,计算速度也很理想。看似没有什么问题,实际上适用场景非常有限,仅适用于一个线程去控制一份数据的情况,大型项目中线程层级关系较多,还是通过数据互斥锁或者设置原子变量的方法来控制

编译 g++ -std=c++11 -pthread test.cpp -o test.exe

参考资料:

  • C++ std::thread
  • C++11并发之std::thread
  • std::thread 学习记录
  • std::thread使用注意事项

示例

// Linux编译:g++ test_thread.cpp -lpthread
#include <iostream>
#include <thread>
#include <atomic>
#include <functional>
#include <mutex>

class CTestThread
{
private:
    /* data */
public:
   
void startThread()
{
    std::lock_guard<std::mutex> g(m_threadMtx);
    if(!m_p_thread){
        m_running = true;
        m_p_thread = new std::thread(std::bind(&CTestThread::runThread,this));
    }
}
void stopThread()
{
    std::lock_guard<std::mutex> g(m_threadMtx);
    if(m_p_thread){
        m_running = false;
        m_p_thread->join();
        delete m_p_thread;
        m_p_thread = nullptr;
    }
}
void runThread()
{
    int num = 0;
    while(m_running)
    {
        std::cout << "thread id:" << std::this_thread::get_id() << " num: " << num++ << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
}


void startThread2()
{
    if(!m_threadrunning){
        m_threadrunning = true;
        m_thread = std::move(std::thread(std::bind(&CTestThread::runThread,this)));
    }
}
void stopThread2()
{
    if(m_threadrunning){
        m_threadrunning = false;
        if (m_thread.joinable())
            m_thread.join();
    }
}

void startThread3()
{
    if(!m_threadrunning){
        m_threadrunning = true;
        m_thread = std::move(std::thread([this](){runThread();}));
    }
}
void stopThread3()
{
    if(m_threadrunning){
        m_threadrunning = false;
        if (m_thread.joinable())
            m_thread.join();
    }
}
 
private:
    std::mutex m_threadMtx;
    std::thread *m_p_thread = nullptr;
    bool m_running = false;


    std::thread m_thread;
    bool m_threadrunning = false;
};

void hello(std::string msg)\
{
    std::cout << "hello  " << msg << std::endl;
}

int main(int argc, char* argv[])
{
    CTestThread testThread;
    testThread.startThread();
    testThread.startThread2();

    CTestThread testThread3;
    testThread3.startThread3();


    std::thread th([]()->void{
        int count = 0;
        while(1){
            count++;
            std::cout << "count: " << count << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    });
    th.detach();

    std::thread th2([=](){
        int age = 0;
        while(1){
            age++;
            std::cout << "age: " << age << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    });
    th2.join(); // 线程不退出会阻塞在这里

    std::thread th4(hello, "LiMing");


// std::thread
// std::bind
// std::move
// 匿名函数
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ std::thread使用 的相关文章

  • 如何从 std::integer_sequence 初始化静态数组?

    我为枚举制作了一个符合以下规则的可迭代生成器 Enum 是一个整数序列 没有间隙 给定枚举的最后一个元素不是实际的枚举元素 该类看起来像这样 template
  • 如何发现 std::vector 的大小/长度(以字节为单位)?

    我有一个向量 我想将其写入文件并将其读取到文件中 但无法使用以下方法确定向量的逻辑大小sizeof操作员 那我该怎么办呢 C std vector 有一个方法size 返回其大小 编辑 据我所知 您现在需要计算给定向量使用的内存 您不能为此
  • C++ 标准中的重载与默认参数

    我正在阅读另一个问题 这引起了我的思考 标准通常会指定在其描述中具有默认参数的函数 标准是否允许将它们写为重载 例如 标准规定std basic string copy有以下声明 size type copy Ch p size type
  • MATLAB 中的统计异常值检测

    假设我们有这个矩阵 main 10000 5 3 1 5 5677 0 134 1 1 456 3 该方法是计量经济学和统计问题中使用最广泛的方法 X是我们正在寻找异常值的数据 X mean X gt n std X 因此 如果这个不等式成
  • noexcept 在派生类中的用法

    我在使用时遇到问题noexcept派生类上的说明符 更准确地说 当父类是抽象类时 具有protected构造函数 以下是我声明类的方式的示例 With a public基类中的构造函数 一切正常 与相同的代码protected并且派生类不再
  • C++ std regex问号问题

    我在使用 std 正则表达式时遇到了麻烦 我无法使问号量词起作用 对 regex match 的调用将始终返回 0 我还尝试了 0 1 它的行为也不像我预期的那样 它的行为就像 量词 这是我的代码 include
  • 是否可以按值删除队列元素?

    我想从队列中删除具有特定值的元素 这样的事该怎么办呢 我正在尝试创建映射和队列的并发混合 目前我尝试在这个答案 https stackoverflow com questions 7704526 is thare in stl or boo
  • 特定于平台的 std::chrono::high_resolution_clock::period::num

    我注意到了std chrono high resolution clock period num 1对于我测试过的每个系统 是否存在任何系统 嵌入式 桌面 移动或其他 它恰好是其他数字 在这样的系统上 1 秒不能用刻度来表示 有以下三种实现
  • C++ - 将 istream_iterator 与 wstringstream 结合使用

    我正在尝试向我编写的程序添加 Unicode 支持 我的 ASCII 代码已编译并包含以下几行 std stringstream stream abc std istream iterator
  • Visual C++ 2010 在调试时拒绝显示 std::string 值。显示<错误指针>

    我有一种奇怪的感觉 就像这是最近出现的问题 并且发生在两台不同的计算机上 当我调试并尝试查看 STL 中的 std string 的值时 它显示为值 它说它的大小是15 容量是一些乱码的巨大数字 数组值本身都显示 CXX0030 错误 无法
  • 如何散列 std::string?

    我正在制作一个小实用程序来帮助我通过重复来记住密码 我想每天只输入一次密码 而不是在每次会话之前输入 当然 我不会存储密码本身 但很乐意存储其哈希值 那么 获取哈希值的最简单方法是什么std string使用 C 标准库 对于不涉及外部库的
  • 最小元素错误

    我不是 C 编码员 所以也许这很容易 我有一个 Point 类向量 我想找到 AABB 矩形 最小 x 最小 y 最小 x 最大 y 最大 x 最小 y 最大 x 最大 y 我已经完成了一个 for 循环 保存最小值和最大值 一次用于 x
  • 如果成功或失败,如何返回 std::copy 的值?

    我在用std copy将对象复制到std deque到一个文件 代码工作正常 但我需要检查复制是否成功 因此我需要设置标志 否则抛出异常 我已经用谷歌搜索但找不到解决方案如何检查是否std copy已成功将值复制到文件中 有人可以照亮它吗
  • C++ TR2 文件系统库的状态如何?

    截至上次布里斯托尔会议 C TR2 文件系统库的状态如何 它将成为 C 1Y C 14 的一部分 还是暂停 或者最近三次会议有任何已知的评论吗 It has 最近获得ISO委员会一致批准 http article gmane org gma
  • 从 boost::shared_ptr 转换为 std::shared_ptr?

    我有一个内部使用 Boost 版本的库shared ptr并且只暴露那些 对于我的应用程序 我想使用std shared ptr只要有可能 遗憾的是 这两种类型之间没有直接转换 因为引用计数的内容取决于实现 有什么办法可以同时拥有boost
  • STL容器的范围插入函数在c ++ 11下返回void?

    刚刚学习c 所以我可能没有正确理解这一点 但我只读到范围插入函数在新标准下返回一个迭代器 C Primer 5th Ed cplusplus com http www cplusplus com reference string basic
  • 计算结构向量中的匹配项

    我有一个问题 要求我计算该数组中使用以下任一方法的实例的数量std count or std find 我知道如何使用标准数据 参见底部代码 类型来执行此操作 但不知道如何使用NameContainer我正在使用的 Type struct
  • 为什么我收到 string does not name a type 错误?

    game cpp include
  • std::copy 的使用错误?

    这是一个简单的测试程序 说明了我遇到的问题 include
  • c++11 中的 std::thread 问题

    我在尝试从标准模板库编译具有多线程的程序时遇到一些麻烦 当我尝试编译以下程序时 它返回一个晦涩的错误 include

随机推荐

  • Ubuntu22.04+Nvidia RTX 3060 显卡驱动安装

    新装 Ubuntu22 04 LTS xff0c 电脑配的是Nvidia RTX 3060 xff0c 所以需要安装显卡驱动 xff0c 未安装前显卡显示如下 xff1a 1 设置阿里源 在软件和更新在第一栏Ubuntu 软件页面中 xff
  • 基于深度学习算法实现视频人脸自动打码

    前言 1 在当下的环境上 xff0c 短视频已是生活的常态 xff0c 但这是很容易就侵犯别人肖像权 xff0c 好多视频都会在后期给不相关的人打上码 xff0c 这里是基于yolov5的人脸检测实现人脸自动打码功能 2 开发环境是win1
  • 树莓派4B设置双网卡静态IP、网卡优先级、查看系统多少位

    1 设置静态IP 下面两种方法都试过 xff0c 可以永久保存 方法2更官方一些 但是 xff0c 方法 1 右上角可视化设置IP不知道为什么无法使用 xff0c 设置好后重启 xff0c 再ping局域网设备 xff0c 总是出现提示 x
  • 基于ZLG/BOOT的linux2.6内核移植(s3c2410)

    基于ZLG BOOT的linux2 6内核移植 s3c2410 ZLG BOOT是广州致远arm实验箱自带的bootloader 我用的这款实验箱自带的linux内核还是2 4版本的 有点儿老了 所 以想移植个2 6上去 由于bootlod
  • Linux如何挂载Windows的NTFS分区?

    使用的是RedHat Linux xff0c 其暂时还不能支持NTFS 分区的直接挂载 xff0c 目前有两种方法可以解决这个问题 一是重新编写Linux 内核 xff0c 二是安装一个功能RPM补丁 本文讨论的是第二种方法 第一步 xff
  • 基于Video4Linux 的USB摄像头图像采集实现

    J W Hu 的 基于Video4Linux 的USB摄像头图像采集实现 Linux本身自带了采用ov511芯片的摄像头 xff0c 而市场上应用最广泛的是采用中 芯微公司生产的zc301芯片的摄像头 xff0c 下面我将针对这两大系列的摄
  • SpringBoot + MyBatisPlus 异常 The SQL execution time is too large, please optimize !

    网上看了很多例子 xff0c 五花八门 xff0c 我是这样解决的 xff0c 配置application yml 把红色那行代码注释掉 xff0c 成功 xff0c 没有出现问题 spring datasource 数据源的基本配置 us
  • ARM-LINUX调试中segmentation fault 的解决参考

    可恶的segmentation fault问题解决探索 xff08 转载 xff09 http oss lzu edu cn blog article php tid 700 html 背景 最近一段时间在linux下用C做一些学习和开发
  • VC 多线程编程

    一 问题的提出 编写一个耗时的单线程程序 xff1a 新建一个基于对话框的应用程序SingleThread xff0c 在主对话框IDD SINGLETHREAD DIALOG添加一个按钮 xff0c ID为IDC SLEEP SIX SE
  • Linux C 函数参考(日期时间)

    1 1 概述 世界标准时间 xff08 Coordinated Universal Time xff0c UTC xff09 xff0c 也就是大家所熟知的格林威治标准时间 xff08 Greenwich Mean Time xff0c G
  • IplImage与char型转换

    对OpenCV稍有了解的同学都知道里边用于存储图像数据的IplImage xff0c 其中有两个属性非常值得关注 xff0c 稍不留神就会导致错误 xff08 后附错例一则 xff09 xff1a 一是width属性 xff1b 二是wid
  • 如何卸载阿里巴巴PC流氓软件

    今天真的是恶心到我了 我有一个移动硬盘插在PC上 xff0c 用了一段时间后本打算简单的退出这个硬盘 xff0c 想安全地拔下 没想到360软件提示有一个进程在占用这个移动硬盘 xff0c 不能安全地弹出 靠 xff0c 我想着什么软件这么
  • wsl1 的Ubuntu20.04升级到wsl2 的Ubuntu20.04失败,报错系统找不到指定的文件

    在wsl下看到Ubuntu 20 0是正常运行的 xff0c 但是升级为wsl2时无法找到对应的文件 PS xff1a 之前将Ubuntu迁移到D盘后删掉了 xff0c 重新下了一个Unbuntu xff0c 可能是导致无法升级wsl2的原
  • 使用U盘重装Windows10系统详细步骤及配图【官方纯净版】

    文章目录 1 制作启动盘1 1准备U盘及一台电脑1 2下载win10安装包 2 安装操作系统2 1插入系统安装盘2 2设置启动盘为第一启动项2 3开始安装操作系统 3 安装成功后进入图形界面3 1启动问题3 2驱动问题3 3调出 34 控制
  • Android实现图片转ascii码字符图的一些尝试

    z2IN png 抖音上炫代码的不少 xff0c 有些真的让人叹为观止 xff0c 作为一个androider xff0c 当我看到下面这段舞蹈的时候 xff0c 终于忍不住了 xff0c 想要通过android实现一样的效果 jileji
  • 浅谈知识追踪(BKT、IRT、DKT)

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言一 知识追踪是什么 xff1f 二 具体内容1 基于贝叶斯的知识追踪 xff08 BKT xff09 项目反应理论 xff0
  • 走进C++11(十四)变长参数模板

    解释 C 43 43 03只有固定模板参数 C 43 43 11 加入新的表示法 xff0c 允许任意个数 任意类别的模板参数 xff0c 不必在定义时将参数的个数固定 变长模板 变长参数是依靠C 43 43 11新引入的参数包的机制实现的
  • sql server 获取当前日期前12个月的月份sql 语句

    sql server 获取当前日期前12个月的月份sql 语句 select convert varchar 7 dateadd mm number dateadd month 11 getdate 120 as dt from maste
  • wxPython禁用窗口最大化按钮

    本文提供了两种方法禁用窗体最大化按钮 方法一 通过SetWindowStyle函数单独设置窗体式样 代码 xff1a self SetWindowStyle wx DEFAULT FRAME STYLE wx MAXIMIZE BOX 方法
  • C++ std::thread使用

    c 43 43 11 之后有了标准的线程库 xff1a std thread 通过c 43 43 11中的线程库创建线程 xff0c 极为方便 xff0c 且跨平台 xff0c 是语言层面的 之前跨平台的多线程开发中 xff0c 多使用bo