• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
MKT-porter
博客园    首页    新随笔    联系   管理    订阅  订阅
c++ 线程函数传递数据 对象和变量 指针 静态成员

 

 

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

  

总结

  1. 在头文件中声明静态变量: static Eigen::Matrix4d mat;
  2. 在源文件中定义静态变量: Eigen::Matrix4d A::mat = Eigen::Matrix4d::Identity();
  3. 在其他源文件中访问和修改静态变量: 使用 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})

  

posted on 2024-07-26 23:41  MKT-porter  阅读(62)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3