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

 

1、为什么需要命名空间

命名空间是ANSI C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。

使用命名空间解决名字冲突

但是,一个大型的应用软件,往往不是由一个人独立完成的,而是由若干不同的人合作完成的,不同的人分别完成不同的部分,最后组成一个完整的程序。

假如不同的人分别定义了类,放在了不同的文件中,在主函数的文件中需要使用这些类时,就用#include指令将这些头文件包含进来。由于头文件室友不同的人设计的,有可能在不同头文件中用了相同的名字来命名所定义的类或函数。这样,程序中就会出现名字冲突。

//PeopleA.h
namespace PeopleA
class Student
{public:
    Student(int n, char s, string name)
    {
        //.....
    }
private:
    int num;
    string name;
    char sex;
};
int fun(int a, int b)
{
    return a + b;
}

//PeopleB.h
namespace PeopleB
class Student
{
public:
    Student(int n, char s, string name)
    {
        //.....
    }
private:
    int num;
    char sex;
    string name;
};
int fun(int a, int b)
{
    return a + b;
}

#include <iostream>
#include "People A.h"
#include "People B.h"
int main()
{
    PeopleA::Student stdu1(101, 18, "wang");
    cout << PeopleA::fun(5, 3) << endl;
    PeopleB::Student stdu1(101, 18, "wang");
    cout << PeopleB::fun(5, 3) << endl;
    return 0;
}

  

2、什么是命名空间

所谓命名空间,实际上就是一个由程序设计者命名的内存区域。

程序设计者可以根据需要制定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。如:

namespace AA
{
    int a;
    double b;
}

namespace是定义命名空间锁必须写的关键字,AA是自己制定的命名空间的名字。

如果在程序中要使用a和b,必须加上命名空间名和作用域分辨符::,如AA::a,AA::b,这种用法称为命名空间限定。
命名空间的作用是建立一些互相分隔的作用域,把一些全局实体分隔开来,以免产生名字冲突。

  

 3 线程间数据传输

是因为定义的是全局变量,全局变量是存在静态区域

全局变量是函数外面定义的,不是主函数内部的开头。

 namespace 只是起了个命名空间。

 

CMakeLists.txt

 

cmake_minimum_required(VERSION 3.10)

# Set the project name
project(GlobalMatrixExample)

# Find Eigen package
find_package(Eigen3 3.3 REQUIRED)

# Find pthread package
find_package(Threads REQUIRED)

# Add executable
add_executable(global_matrix_example main.cpp)

# Link Eigen3 and pthreads to the target
target_link_libraries(global_matrix_example Eigen3::Eigen Threads::Threads)

  main.cpp

#include <iostream>
#include <Eigen/Dense>
#include <thread>
#include <mutex>

/*
多线程是可以访问全局变量的,只要注意互锁
1 配合namespace能够清楚区分这是哪个全局变量

namespace 用于组织和管理代码的作用域,使得不同部分的代码能够清晰地分隔和访问共享的数据或功能。
指针用于直接操作和访问内存中的数据,允许动态内存分配和传递数据的引用。

namespace 通过定义全局变量来实现数据共享,这些变量可以在整个程序中访问,但它们的访问和修改需要保证线程安全。
指针通过传递内存地址来实现数据共享,可以在多个线程或函数之间共享和修改数据,指针操作本身并不保证线程安全,必须通过额外的机制(如互斥量)来保护数据的访问。

static全局变量与普通的全局变量有什么区别 ?
 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。
 全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。
 这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。 
 static全局变量只初使化一次,防止在其他文件单元中被引用; 

*/

// 全局变量-而非主函数中开头定义的主函数内部全局变量
namespace MyNamespace {
    // 全局变量
    Eigen::Matrix4d globalMatrix;
    double globalValue = 0.0;
    std::mutex matrixMutex; // 用于保护 globalMatrix 的互斥锁

}

// 修改矩阵的线程函数
void modifyMatrix(int threadId) {
    std::lock_guard<std::mutex> lock(MyNamespace::matrixMutex); // 锁定互斥锁
    MyNamespace::globalMatrix(0, threadId) = threadId; // 修改矩阵中的一个元素

    MyNamespace::globalValue += threadId * 1.0;
    std::cout << "Thread " << threadId 
    << " modified matrix:\n" << MyNamespace::globalMatrix 
    << " \n updated globalValue to " << MyNamespace::globalValue 
    << std::endl;
}

int main() {
    // 初始化矩阵
    MyNamespace::globalMatrix.setZero();

    // 创建多个线程
    std::thread t1(modifyMatrix, 1);
    std::thread t2(modifyMatrix, 2);
    std::thread t3(modifyMatrix, 3);

    // 等待所有线程完成
    t1.join();
    t2.join();
    t3.join();

    // 输出最终矩阵
    std::cout << "Final matrix:\n" << MyNamespace::globalMatrix 
    << " \n Main thread final globalValue: " << MyNamespace::globalValue 
    << std::endl;

    return 0;
}

  

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