在模拟代码中使用全局变量

发布于 2024-11-26 00:29:16 字数 377 浏览 0 评论 0原文

可能的重复:
全局变量不好吗?

我正在编写一个利用材料和能源特定数据的模拟代码。这些数据存储在全局数组中,因为一旦上传,它们就会在模拟过程中使用,并且应该可以被大多数函数访问。

我到处都读到使用全局变量不是一个好习惯。 有人可以向我解释一下,或者向我指出网络上的材料,解释如何在需要使用大量数据数组时避免在模拟应用程序编码中使用全局数组。我尝试用 C++ 编写代码,并尽可能多地使用面向对象的功能。

预先感谢您的帮助。

Possible Duplicate:
Are global variables bad?

I am writing a simulation code making use of material and energy specific data. This data is stored in global arrays, because once uploaded, they are used during the simulation and should be accessible by most of the functions.

I read everywhere that it is not good practice to use global variables.
Could someone explain me or point me to material on the web explaining how I could avoid using global arrays in simulation application coding while massive data arrays need to be used. I try to code in C++ and make use as much as possible of object oriented features.

Thanks in advance for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

べ繥欢鉨o。 2024-12-03 00:29:16

您说得对,不建议使用全局变量。您可以在命名空间内声明那些不相关的golbals,

//Globals.h
namespace Globals
{
  extern int a[100];
  extern double d;
}

并在.cpp文件中定义它们。

//Globals.cpp
int Globals::a[100] = { ... };
double Globals::d = 3.14;

现在将它们用作 Globals::aGlobals::d 等。我的答案是从代码管理的角度来看。

You are right about the fact that, using globals are not recommended. You can declare those unrelated golbals inside a namespace,

//Globals.h
namespace Globals
{
  extern int a[100];
  extern double d;
}

and define them in a .cpp file.

//Globals.cpp
int Globals::a[100] = { ... };
double Globals::d = 3.14;

Now use them as Globals::a, Globals::d etc. My answer is in code management perspective.

不气馁 2024-12-03 00:29:16

是的,你是对的,全局变量不好。
这是一个有用的链接,它解释了为什么全局变量不好以及如何避免它们。

http://c2.com/cgi/wiki?GlobalVariablesAreBad

编辑:
@sergio's post也指向相同的链接,你可以忽略这个答案

Yes you are right, global variables are not good.
This is a useful link which explains why global variables are bad and how to avoid them.

http://c2.com/cgi/wiki?GlobalVariablesAreBad

EDIT:
@sergio's post also points to the same link, you can ignore this answer

回忆追雨的时光 2024-12-03 00:29:16

有人可以向我解释一下,或者向我指出网络上的材料,解释如何在需要使用大量数据数组时避免在模拟应用程序编码中使用全局数组。

与通常避免全局变量的方式相同:使用局部变量。将数据输入函数的自然方法是将其作为参数传递。这并不昂贵,特别是如果您在适当的情况下通过引用传递的话。

Could someone explain me or point me to material on the web explaining how I could avoid using global arrays in simulation application coding while massive data arrays need to be used.

The same way you avoid globals in general: by using locals instead. The natural way to get data into a function is to pass it as a parameter. This is not expensive, especially if you pass by reference where appropriate.

薔薇婲 2024-12-03 00:29:16

请查看这篇关于全局变量的文章。这是摘录:

为什么不必要时应避免使用全局变量

非局部性——当源代码的各个元素的范围受到限制时,源代码最容易理解。全局变量可以由程序的任何部分读取或修改,因此很难记住或推理每种可能的用途。

无访问控制或约束检查——程序的任何部分都可以获取或设置全局变量,并且有关其使用的任何规则都可以很容易地被破坏或忘记。 (换句话说,get/set 访问器通常比直接数据访问更可取,对于全局数据更是如此。)推而广之,缺乏访问控制会极大地阻碍在您可能希望运行不受信任的代码的情况下实现安全性(例如使用第三方插件)。

隐式耦合——具有许多全局变量的程序通常在其中一些变量之间以及变量和函数之间具有紧密耦合。将耦合项分组为有凝聚力的单元通常会产生更好的程序。

并发问题——如果全局变量可以被多个执行线程访问,那么同步是必要的(而且常常被忽视)。当动态链接模块与全局变量时,即使在数十个不同上下文中测试的两个独立模块是安全的,组成的系统也可能不是线程安全的。

命名空间污染——全局名称随处可见。当您认为自己正在使用本地变量(通过拼写错误或忘记声明本地变量)时,您可能会在不知不觉中最终使用全局变量,反之亦然。另外,如果您必须将具有相同全局变量名称的模块链接在一起,如果幸运的话,您将收到链接错误。如果不幸的话,链接器将简单地将所有使用相同名称的情况视为同一对象。

内存分配问题——某些环境的内存分配方案使全局变量的分配变得棘手。在“构造函数”具有分配以外的副作用的语言中尤其如此(因为在这种情况下,您可以表达两个全局变量相互依赖的不安全情况)。此外,当动态链接模块时,可能不清楚不同的库是否有自己的全局实例,或者全局变量是否是共享的。

测试和限制 - 使用全局变量的源代码测试起来有些困难,因为无法在运行之间轻松设置“干净”的环境。更一般地说,由于同样的原因,使用未明确提供给该源的任何类型的全局服务(例如读取和写入文件或数据库)的源很难进行测试。对于通信系统,测试系统不变量的能力可能需要同时运行多个系统“副本”,这会受到任何共享服务(包括全局内存)的使用的极大阻碍,而共享服务并未作为测试的一部分提供共享.

它还讨论了几种替代方案。可能在您的情况下,您可以考虑:

  1. 隐藏全局变量(例如私有静态变量);

  2. 有状态过程:setter 和 getter 函数允许访问数组,同时也“屏蔽”它;

  3. 单例模式

编辑:

我知道开发社区的一部分反对使用单例模式。我完全尊重这个意见。无论如何,在当前讨论的背景下,单例与全局变量的原始使用相比具有几个优点:

  1. 改进的访问控制;

  2. 同步的机会;

  3. 抽象实现的能力。

在这方面,一组 setter/getter 函数并没有更好,但也不算更差。我把选择如何处理他自己的代码的艰巨任务留给了OP。 (顺便说一句,本文讨论了更多方法,例如上下文对象、依赖注入等)。

Have a look at this article about global variables. This is an excerpt:

Why Global Variables Should Be Avoided When Unnecessary

Non-locality -- Source code is easiest to understand when the scope of its individual elements are limited. Global variables can be read or modified by any part of the program, making it difficult to remember or reason about every possible use.

No Access Control or Constraint Checking -- A global variable can be get or set by any part of the program, and any rules regarding its use can be easily broken or forgotten. (In other words, get/set accessors are generally preferable over direct data access, and this is even more so for global data.) By extension, the lack of access control greatly hinders achieving security in situations where you may wish to run untrusted code (such as working with 3rd party plugins).

Implicit coupling -- A program with many global variables often has tight couplings between some of those variables, and couplings between variables and functions. Grouping coupled items into cohesive units usually leads to better programs.

Concurrency issues -- if globals can be accessed by multiple threads of execution, synchronization is necessary (and too-often neglected). When dynamically linking modules with globals, the composed system might not be thread-safe even if the two independent modules tested in dozens of different contexts were safe.

Namespace pollution -- Global names are available everywhere. You may unknowingly end up using a global when you think you are using a local (by misspelling or forgetting to declare the local) or vice versa. Also, if you ever have to link together modules that have the same global variable names, if you are lucky, you will get linking errors. If you are unlucky, the linker will simply treat all uses of the same name as the same object.

Memory allocation issues -- Some environments have memory allocation schemes that make allocation of globals tricky. This is especially true in languages where "constructors" have side-effects other than allocation (because, in that case, you can express unsafe situations where two globals mutually depend on one another). Also, when dynamically linking modules, it can be unclear whether different libraries have their own instances of globals or whether the globals are shared.

Testing and Confinement - source that utilizes globals is somewhat more difficult to test because one cannot readily set up a 'clean' environment between runs. More generally, source that utilizes global services of any sort (e.g. reading and writing files or databases) that aren't explicitly provided to that source is difficult to test for the same reason. For communicating systems, the ability to test system invariants may require running more than one 'copy' of a system simultaneously, which is greatly hindered by any use of shared services - including global memory - that are not provided for sharing as part of the test.

It also discusses several alternatives. Possibly in your case, you could consider:

  1. hiding your globals (e.g., private static variables);

  2. stateful procedures: setter and getter functions allowing access to the arrays while also "masking" it;

  3. the singleton pattern.

EDIT:

I understand that a part of the development community are against the use of the singleton pattern. I fully respect this opinion. Anyway, in the context of the present discussion, the singleton offers several advantages over the raw use of globals:

  1. improved access control;

  2. opportunity for synchronization;

  3. ability to abstract away the implementation.

In this respect, it is not better from a setter/getter set of functions, but still, not worse. I leave to the OP the hard task of choosing what to do with his own code. (BTW, the article discusses more approaches, like Context Objects, DependencyInjection, etc).

权谋诡计 2024-12-03 00:29:16

在代码中引入全局状态可能会使以多线程方式执行操作变得困难。

我还认为它会使代码的意图更难以遵循。如果将所有参数作为参数传递给函数,至少可以清楚函数可以访问哪些数据以及哪些数据可能会更改。使用全局变量并没有给阅读代码的人这个机会......

使用全局变量通常不会更快。如果您有需要传递给函数的大型对象,请通过引用传递这些参数,并且复制不会出现任何问题。

如果不了解更多有关您的设置的信息,就很难提出任何建议,但如果您有大量数据需要传递给一系列例程,我会很想将其全部放入一个结构中code>,并通过引用传递该 struct

struct my_data_type
{
    double some_data;
    double some_other_data;

    std::vector<double> some_coefficients;
    std::vector<double> some_other_coefficients;

    std::string some_name;
    std::string some_other_name;

    // add more members as necessary...
};

void foo(my_data_type &data)
{
    // there's no big overhead passing data by reference
}

如果您只需要以只读方式访问数据,最好作为 const 引用传递:

void foo(my_data_type const&data)
{
    // again, efficient, but ensures that data can't be modified
}

编辑: 对于你的评论,我不是谈论“全球”结构。您需要声明一个本地 struct 变量,将文件中的数据读取到 struct 中,然后通过引用将其传递给需要调用的任何函数:

int main()
{
    // a local struct to encapsulate the file data
    my_data_type file_data;

    // read the data from your file into file_data

    // the struct containing the data is passed by reference
    foo(file_data);

    return 0;
}

Introducing global state into your code can make it difficult to do things in a multi-threaded way.

I would also argue it can make the intent of your code more difficult to follow. If you pass all of the arguments to a function as parameters at least it's clear what data the function has access to, and what has the potential of changing. The use of global variables doesn't give someone reading the code this chance...

It's also not generally true that using global variables is in any way faster. If you have large objects that you need to pass to functions, pass these arguments via references and there won't be any issues with copying.

Without knowing more about your setup, it's difficult to make any recommendations, but if you have a large amount of data that needs to be passed around to a series of routines I would be tempted to put it all in a struct, and to pass that struct by reference:

struct my_data_type
{
    double some_data;
    double some_other_data;

    std::vector<double> some_coefficients;
    std::vector<double> some_other_coefficients;

    std::string some_name;
    std::string some_other_name;

    // add more members as necessary...
};

void foo(my_data_type &data)
{
    // there's no big overhead passing data by reference
}

If you only need to access the data in a read-only fashion, it's best to pass as a const reference:

void foo(my_data_type const&data)
{
    // again, efficient, but ensures that data can't be modified
}

EDIT: In answer to your comment, I'm not talking about a "global" structure. You would need to declare a local struct variable, read the data from your file into the struct and then pass it by reference to any functions that need to be called:

int main()
{
    // a local struct to encapsulate the file data
    my_data_type file_data;

    // read the data from your file into file_data

    // the struct containing the data is passed by reference
    foo(file_data);

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文