例子1 通过类引用 线程传递


CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(MyProject) # 查找并添加线程库 find_package(Threads REQUIRED) # 添加可执行文件 add_executable(my_program main.cpp) # 添加线程库链接 target_link_libraries(my_program Threads::Threads)
main.cpp
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
//#include <chrono>
#include <unistd.h> // For sleep()
using namespace std;
std::mutex mtx2;
class MyObject {
private:
std::vector<int> data; // vector 数据成员
bool flag; // bool 数据成员
std::mutex mtx; // 互斥锁,保护对象数据的访问
public:
MyObject(const std::vector<int>& d, bool f) : data(d), flag(f) {}
void modifyVector() {
//std::lock_guard<std::mutex> lock(mtx); // 上锁作用于结束自动关锁
mtx.lock(); // 上锁
for (int i = 0; i < data.size(); ++i) {
data[i] *= 2; // 修改 vector 中的每个元素
}
mtx.unlock(); // 解锁
}
void modifyBool(bool newFlag) {
std::lock_guard<std::mutex> lock(mtx); // 上锁
flag = newFlag; // 修改 bool 变量
}
const std::vector<int>& getVector() const {
return data;
}
bool getBool() const {
return flag;
}
};
// 第一个线程函数
void threadFunction1(MyObject& obj,bool &new_gnss) {
while (1)
{
sleep(5);
obj.modifyVector();
obj.modifyBool(true);
std::lock_guard<std::mutex> lock(mtx2); // 自动上锁关锁
new_gnss=1;
std::cout << "Thread 1 发送数据 " << obj.getBool()<< " "<< new_gnss <<std::endl;
}
}
// 第二个线程函数
void threadFunction2(MyObject& obj,bool &new_gnss) {
while (1)
{
sleep(1);
obj.modifyVector();
obj.modifyBool(false);
std::lock_guard<std::mutex> lock(mtx2); // 自动上锁关锁
if(new_gnss){
std::cout << "线程2 新数据到达" <<endl;
new_gnss=0;
}
else{
std::cout << "线程2 没有新数据到达" <<endl;
}
//std::cout << "Thread 2 modified data " << obj.getBool() << " "<< new_gnss <<std::endl;
}
}
int main() {
std::vector<int> initData = {1, 2, 3, 4, 5};
MyObject obj(initData, false);
bool new_gnss=0;
// 创建两个线程并开始执行,传递对象引用
std::thread t1(threadFunction1, std::ref(obj),std::ref(new_gnss));
std::thread t2(threadFunction2, std::ref(obj),std::ref(new_gnss));
// 等待两个线程执行完毕
t1.join();
t2.join();
// 输出最终的对象数据
const std::vector<int>& finalVector = obj.getVector();
std::cout << "Final contents of vector:";
for (auto num : finalVector) {
std::cout << " " << num;
}
std::cout << std::endl;
bool finalBool = obj.getBool();
std::cout << "Final value of bool: " << std::boolalpha << finalBool << std::endl;
return 0;
}
2 通过类的指针 线程传递

对比引用和指针区别
#include <iostream>
// 定义一个简单的类 MyClass
class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
};
// 修改传入对象的状态,传入的是对象的副本
void modifyObjectCopy(MyClass obj) {
obj.value = 100; // 修改传入对象的副本
}
// 修改会影响原始对象的状态,传入对象的引用
void modifyObjectReference(MyClass &ref) {
ref.value = 100; // 修改传入对象的值
}
// 使用指针修改传入对象的状态,需检查空指针
void modifyObjectPointer(MyClass *ptr) {
if (ptr != nullptr) {
ptr->value = 100; // 修改传入对象的值
}
}
int main() {
// 创建 MyClass 对象
MyClass obj(10);
// 演示修改传入对象的状态,传入对象的副本
modifyObjectCopy(obj); // 传递对象的副本
std::cout << "After modifyObjectCopy, Original value: " << obj.value << std::endl; // 输出原始对象的值,未被修改
// 演示修改会影响原始对象的状态,传入对象的引用
modifyObjectReference(obj); // 直接传递对象引用
std::cout << "After modifyObjectReference, Modified value: " << obj.value << std::endl; // 输出修改后的值
// 演示使用指针修改传入对象的状态,传入对象的地址
modifyObjectPointer(&obj); // 传递对象的地址
std::cout << "After modifyObjectPointer, Modified value: " << obj.value << std::endl; // 输出修改后的值
return 0;
}
3 通过static 共享所有类的同一个数据
在类中,静态成员可以实现多个对象之间的数据共享
使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。
(1) 初始化在类体外进行,而前面不加static,(这点需要注意)以免与一般静态变量或对象相混淆。
1 class StaticTest
2 {
3 public:
4 StaticTest(int a, int b, int c);
5 void GetNumber();
6 void GetSum();
7 static void f1(StaticTest &s);
8 private:
9 int A, B, C;
10 static int Sum;
11 };
12
13
14
15 #include "StaticTest.h"
16 #include <iostream>
17 using namespace std;
18
19 int StaticTest::Sum = 0;//静态成员在此初始化
20
21 StaticTest::StaticTest(int a, int b, int c)
22 {
23 A = a;
24 B = b;
25 C = c;
26 Sum += A + B + C;
27 }
28
29 void StaticTest::GetNumber()
30 {
31 cout << "Number = " << endl;
32 }
33
34 void StaticTest::GetSum()
35 {
36 cout << "Sum = " << Sum <<endl;
37 }
38
39 void StaticTest::f1(StaticTest &s)
40 {
41
42 cout << s.A << endl;//静态方法不能直接调用一般成员,可以通过对象引用实现调用
43 cout << Sum <<endl;
44 }
45
46 #include "StaticTest.h"
47 #include <stdlib.h>
48
49
50 int main(void)
51 {
52 StaticTest M(3, 7, 10), N(14, 9, 11);
53 M.GetNumber();
54 N.GetSum();
55 M.GetNumber();
56 N.GetSum();
57 StaticTest::f1(M);
58 system("pause");
59 return 0;
60 }
注意,static成员的初始化要在实现中进行,不能在头文件进行。
在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:<类名>::<静态成员函数名>(<参数表>);
静态成员样例3 不同文件
a.h:
首先,在类的头文件(假设是 a.h)中声明静态变量。你需要在类中声明静态变量的存在,但不进行定义(即不分配内存)。
#ifndef A_H
#define A_H
#include <Eigen/Dense>
class A {
public:
static Eigen::Matrix4d mat; // 静态成员变量声明
};
#endif // A_H
a.cpp:
在类的源文件(假设是 a.cpp)中,你需要定义静态变量。这里你为静态变量分配内存。
#include "a.h" // 静态成员变量定义 Eigen::Matrix4d A::mat = Eigen::Matrix4d::Identity(); // 初始化为单位矩阵(或其他默认值)
修改静态变量
main.cpp:
#include <iostream>
#include "a.h"
int main() {
// 打印静态变量的初始值
std::cout << "Initial matrix:\n" << A::mat << std::endl;
// 修改静态变量
A::mat << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16;
// 打印修改后的值
std::cout << "Modified matrix:\n" << A::mat << std::endl;
return 0;
}
总结
- 在头文件中声明静态变量:
static Eigen::Matrix4d mat; - 在源文件中定义静态变量:
Eigen::Matrix4d A::mat = Eigen::Matrix4d::Identity(); - 在其他源文件中访问和修改静态变量: 使用
A::mat来访问和修改这个静态成员。
确保你在编译和链接时包含了所有相关的源文件(a.cpp 和 main.cpp),并且 Eigen 库已经正确地配置和链接到你的项目中。
静态成员样例2 同文件

main.cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <Eigen/Dense>
#include <chrono>
/**
* 在 C++ 中,类不能直接声明为 static。
* 但是,类中的成员(包括静态成员)可以是 static。static 修饰符用于标识静态成员变量和静态成员函数,它们属于类而不是类的实例。
*/
class A {
public:
static Eigen::Matrix4d T_4X4;
static Eigen::Matrix3d R;
static Eigen::Vector3d t;
static double s;
static std::mutex mtx;
class B {
public:
static Eigen::Matrix4d T_4X4;
};
static void updateAll(const Eigen::Matrix4d& T_, const Eigen::Matrix3d& R_, const Eigen::Vector3d& t_, double s_) {
std::lock_guard<std::mutex> lock(mtx);
T_4X4 = T_;
R = R_;
t = t_;
s = s_;
}
static void printAll() {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Matrix4d:\n" << T_4X4 << "\n";
std::cout << "Matrix3d:\n" << R << "\n";
std::cout << "Vector3d:\n" << t << "\n";
std::cout << "Double: " << s << "\n";
}
};
//
class A;
Eigen::Matrix4d A::T_4X4 = Eigen::Matrix4d::Identity();//单位矩阵是一个对角线上的元素为 1,其余元素为 0 的方阵。
Eigen::Matrix3d A::R = Eigen::Matrix3d::Identity();//单位矩阵是一个对角线上的元素为 1,其余元素为 0 的方阵。
Eigen::Vector3d A::t = Eigen::Vector3d::Zero();
double A::s = 0.0;
std::mutex A::mtx;
// 定义静态成员
Eigen::Matrix4d A::B::T_4X4 = Eigen::Matrix4d::Identity();
void threadFunction(double &message) {
Eigen::Matrix4d newMatrix4d = Eigen::Matrix4d::Identity()*message;
Eigen::Matrix3d newMatrix3d = Eigen::Matrix3d::Identity()*message;
Eigen::Vector3d newVector3d = Eigen::Vector3d::Identity()*message;
double newValue = message;
A::updateAll(newMatrix4d, newMatrix3d, newVector3d, newValue);
//A::printAll();
std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main() {
double id_=1;
std::thread t1(threadFunction,std::ref(id_));
std::this_thread::sleep_for(std::chrono::seconds(1));
A::printAll();
id_=2;
std::thread t2(threadFunction,std::ref(id_));
std::this_thread::sleep_for(std::chrono::seconds(1));
A::printAll();
t1.join();
t2.join();
A::printAll();
// 访问静态成员
std::cout << "Matrix T_4X4:\n" << A::B::T_4X4 << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# 项目名称
project(ThreadSafeEigenExample)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Eigen 路径设置 (请根据实际路径修改)
# 你可以从系统的 Eigen 安装目录找到 CMake 配置文件,或指定 Eigen 的路径
find_package(Eigen3 REQUIRED NO_MODULE)
find_package(Threads REQUIRED)
# 添加可执行文件
add_executable(ThreadSafeEigenExample main.cpp)
# 链接 Eigen 库
target_link_libraries(ThreadSafeEigenExample Eigen3::Eigen ${CMAKE_THREAD_LIBS_INIT})
浙公网安备 33010602011771号