例子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})