当我们可以选择将变量设为外部时,为什么要通过引用传递?

发布于 2024-09-28 19:18:59 字数 277 浏览 5 评论 0原文

假设我们有一个数组,说:

int arr[1000];

并且我有一个作用于该数组的函数,说:

void Func(void);

当我可以将 arr[1000] 作为外部变量时,为什么需要通过引用传递(通过更改 void)主要的()?

  1. 有什么区别吗?有什么区别吗?
  2. 为什么人们更喜欢通过引用传递而不是将其外部化? (我自己认为将其外部化更容易)。

Suppose we have an array say:

int arr[1000];

and I have a function that works on that array say:

void Func(void);

Why would there ever be a need to pass by reference (by changing the void), when I can have arr[1000] as an external variable outside main()?

  1. What is the difference?Is there any difference?
  2. Why do people prefer passing by reference rather than making it external? (I myself think that making it external is easier).

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

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

发布评论

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

评论(9

幼儿园老大 2024-10-05 19:18:59

如果您使用全局变量 arr,则 Func 仅限于始终与该变量一起使用,而不能与其他变量一起使用。以下是这可能不好的一些原因:

  • arr 是您正在使用的“当前文档”的一部分,并且您后来决定希望您的程序支持打开多个文档。
  • 您后来决定(或者使用您的代码作为库的某人决定)使用线程,当两个线程在 arr 中互相破坏彼此的工作时,您的程序突然随机崩溃。
  • 您稍后决定将您的代码设为一个库,现在为调用者提供缓冲区是有意义的(以防程序中多次使用该库);否则,调用代码的独立部分将了解彼此的实现。

一旦消除了全局变量并使函数采用指向它们需要操作的数据的指针,所有这些问题就会消失。

If you use a global variable arr, Func is limited to always being used with that one variable and nothing else. Here are some reasons why that might be bad:

  • arr is part of the "current document" you're working with, and you later decide you want your program to support having more than one document open.
  • You later decide (or someone using your code as a library decides) to use threads, and suddenly your program randomly crashes when two threads clobber each other's work in arr.
  • You later decide to make your code a library, and now it makes sense for the caller (in case there's more than one point at which the library gets used in a program) to provide the buffer; otherwise independent parts of the calling code would have the be aware of one another's implementations.

All of these problems go away as soon as you eliminate global variables and make your functions take pointers to the data they need to operate on.

我一向站在原地 2024-10-05 19:18:59

我认为您是在问全局变量是否不好。引用一个很好的答案

全局变量的问题是
因为每个函数都可以访问
对于这些,变得越来越困难
找出实际有哪些功能
读取和写入这些变量。

了解应用程序如何
有效,你几乎必须采取
考虑到每一个功能
修改全局状态。那可以是
完成,但随着应用程序的增长
会变得更加困难
几乎不可能(或至少
完全浪费时间)。

如果不依赖全局变量,
你可以在之间传递状态
根据需要提供不同的功能。那
这样你就有更好的机会
了解每个功能的作用,
因为你不需要全局
考虑到状态。

I think you're asking if global variables are bad. Quoting an excellent answer:

The problem with global variables is
that since every function has access
to these, it becomes increasingly hard
to figure out which functions actually
read and write these variables.

To understand how the application
works, you pretty much have to take
into account every function which
modifies the global state. That can be
done, but as the application grows it
will get harder to the point of being
virtually impossible (or at least a
complete waste of time).

If you don't rely on global variables,
you can pass state around between
different functions as needed. That
way you stand a much better chance of
understanding what each function does,
as you don't need to take the global
state into account.

浅忆流年 2024-10-05 19:18:59

如果arr是外部的,那么任何人都可以修改它,而不仅仅是Func。这绝对是坏事。

传递参数可确保您知道正在更改哪些数据以及谁在更改数据。

编辑:官方不好的意思是“通常不好,但并非总是如此。除非有充分的理由,否则通常不要这样做。”就像软件开发的所有其他“规则”一样:)

If arr is external then anyone can modify it, not just Func. This is Officially Bad.

Passing arguments ensures that you know what data you are changing and who is changing it.

EDIT: Where Officially Bad means "Usually bad, but not always. Generally don't do it unless you have a good reason." Just like all the other "rules" of software development :)

执着的年纪 2024-10-05 19:18:59

通过将变量设置为函数的外部,该函数现在紧密耦合到定义该变量的模块,因此更难在其他程序中重用。这也意味着您的函数只能在该一个数组上运行,这限制了函数的灵活性。假设有一天您的需求发生了变化,现在您必须使用 Func 处理多个数组。

通过将数组作为参数(以及数组大小)传递,该函数可以更轻松地与使用它的模块解耦(这意味着它可以更容易地被其他程序/模块使用),并且您现在可以使用该函数处理多个数组。

从一般代码维护的角度来看,函数及其调用者最好通过参数和返回值进行通信,而不是依赖共享变量。

By making the variable external to the function, the function is now tightly coupled to the module that defines the variable, and is thus harder to reuse in other programs. It also means that your function can only ever work on that one array, which limits the function's flexibility. Suppose one day your requirements change, and now you have to process multiple arrays with Func.

By passing the array as a parameter (along with the array size), the function becomes more easily decoupled from the module using it (meaning it can be more easily used by other programs/modules), and you can now use the function to process more than one array.

From a general code maintenance standpoint, it's best that functions and their callers communicate through parameters and return values rather than rely on shared variables.

音盲 2024-10-05 19:18:59

这很大程度上是一个范围问题;如果您将所有变量都设置为外部/全局范围内的变量,那会变得多么混乱?

不仅如此,您还将拥有大量在任何给定时间都不需要存在的变量。传递函数参数而不是使用大量全局变量可以让您更轻松地摆脱不再需要的东西。

It's largely a matter of scope; If you make all your variables external/global in scope, how confusing is that going to get?

Not only that, but you'll have a large number of variables that simply do not need to exist at any given time. Passing function arguments around instead of having lots of global variables lets you more easily get rid of things you no longer need.

薄荷→糖丶微凉 2024-10-05 19:18:59

通过引用传递(而不是使用全局变量)可以让阅读代码的人更清楚地知道该函数可能会更改数组的值。

此外,如果您想要对多个数组执行操作,您可以一遍又一遍地使用相同的函数,并每次向其传递一个不同的数组。

另一个原因是,在编写多线程代码时,您通常希望每个线程独占拥有它必须处理的尽可能多的数据(共享可写数据的成本很高,如果做得不好,可能会导致竞争条件)。通过限制全局变量访问并创建局部变量并传递引用,您可以更轻松地编写对线程(和信号处理程序)更友好的代码。

作为一个例子,让我们看一下简单的 puts 函数。

int puts(const char *s);

该函数将 C 字符串写入标准输出,这很有用。您可能会编写一些复杂的代码,使用 puts 输出有关其在不同执行阶段正在执行的操作的消息。

 int my_complicated_code( int x, int y, int z);

现在,想象一下您在程序中多次调用该函数,但其​​中一次您实际上不希望它写入标准输出,而是写入其他一些FILE *。如果对 puts 的所有调用实际上都是 fputs,它采用一个 FILE * 来告诉要打印到哪个文件,这将很容易如果您更改 my_complicated_code 以接受 FILE * 及其其他参数,即可完成。

 int my_complicated_code(int x, int y, int z, FILE * out_file);

现在,您可以通过向其传递对您拥有的任何 FILE * 的引用(可供写入)来决定在调用 my_complicated_code 时它将打印到哪个文件。

对于数组也是如此。如果 memcpy 函数仅将数据复制到一个特定位置,那么它的用处就会小很多。或者,如果它仅从一个特定位置复制,因为它实际上需要两个对数组的引用。

为也采用引用的函数编写单元测试通常更容易,因为它们不会假设所需数据在哪里或其名称是什么。您不必不断更新具有特定名称的数组来模仿您要测试的输入,只需为每个测试创建一个不同的数组并将其传递给您的函数即可。

在许多简单的程序中,使用这样的全局变量编写代码似乎更容易,但随着程序变得越来越大,情况并非如此。

Passing by reference (rather than using a global variable) makes it more clear to someone reading the code that the function may change the values of the array.

Additionally if you were to want to preform the action on more than one array you could just use the same function over and over and pass a different array to it each time.

Another reason is that when writing multi-threaded code you usually want each thread to exclusively own as much of the data that it has to work on (sharing writable data is expensive and may result in race conditions if not done properly). By restricting global variable access and making local variables and passing references you can more easily write code that is more thread (and signal handler) friendly.

As an example lets look at the simple puts function.

int puts(const char *s);

This function write a C string to standard output, which can be useful. You might write some complicated code that outputs messages about what it is doing at different stages of execution using puts.

 int my_complicated_code( int x, int y, int z);

Now, imagine that you call the function several times in the program, but one of those times you actually don't want it to write to standard output, but to some other FILE *. If all of your calls to puts were actually fputs, which takes a FILE * that tells what file to print to, this would be easy to accomplish if you changed my_complicated_code to take in a FILE * as well as it's other arguments.

 int my_complicated_code(int x, int y, int z, FILE * out_file);

Now you can decide which file it will print to at the time when you call my_complicated_code by passing it a reference to any FILE * you have (that is open for writing).

The same thing follows for arrays. The memcpy function would be much less useful if it only copied data to one particular location. Or if it only copied from one particular location, since it actually takes two references to arrays.

It is often easier to write unit tests for functions that take references too since they don't make assumptions about where the data they need is or what its name is. You don't have to keep updating an array with a certain name to mimic the input you want to test, just create a different array for each test and pass it to your function.

In many simple programs it may seem like it is easier to write code using global variables like this, but as programs get bigger this is not the case.

萌辣 2024-10-05 19:18:59

作为已经给出充分理由的所有其他答案的补充:编程中的每一个决定都是不同优点和缺点之间的权衡。几代程序员几十年的编程经验表明,全局状态在大多数情况下是一件坏事。甚至有一个围绕避免它而构建的编程范例,将其发挥到完全避免状态的极端:

http ://en.wikipedia.org/wiki/Functional_programming

您现在可能会发现它更容易,但是当您的项目不断变得越来越大时,在某些时候您会发现您已经实现了很多解决方法对于这期间出现的问题,你会发现自己无法维护自己的代码。

As an addition to all the other answers already giving good reasons: Every single decision in programming is a tradeoff between different advantages and disadvantages. Decades of programming experience by generations of programmers have shown that global state is a bad thing in most cases. There is even a programming paradigm built around the avoidance of it, taking it to the extreme of avoiding state at all:

http://en.wikipedia.org/wiki/Functional_programming

You may find it easier at the moment, but when your projects keep going to grow bigger and bigger, at some point you will find that you have implemented so many workarounds for the problems that came up in the meantime, that you will find yourself unable to maintain your own code.

旧故 2024-10-05 19:18:59
  1. 范围有所不同。如果你声明“int arr[1000]”
    例如,在 main() 中,您无法在函数“another_function()”中访问它。您必须通过引用显式地将其传递给要在其中使用它的每个其他函数。如果它是外部的,那么每个函数都可以访问它。

  2. 请参阅 (1.)

  1. There is a difference in scope. If you declare "int arr[1000]"
    in your main() for instance, you cannot access it in your function "another_function()". You would have to explicitly pass it by reference to every other function in which you want to use it. If it were external, it would be accessible in every function.

  2. See (1.)

贱人配狗天长地久 2024-10-05 19:18:59

这也是一个维护问题。当我可以查看该函数并了解它应该是什么时,为什么我必须在某个地方追踪一些外部内容?

It's a maintenance issue too. Why would I want to have to track down some external somewhere when I can just look at the function and see what it is supposed to be?

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