在 API 设计中什么时候应该使用指针而不是引用?

发布于 2024-11-29 12:41:59 字数 901 浏览 2 评论 0 原文

我了解指针与引用的语法和一般语义,但我应该如何决定何时在 API 中使用引用或指针或多或少合适?

当然,有些情况需要其中之一(operator++ 需要一个引用参数),但总的来说,我发现我更喜欢使用指针(和 const 指针),因为语法很清楚,变量正在被破坏性地过去了。

例如,在下面的代码中:

void add_one(int& n) { n += 1; }
void add_one(int* const n) { *n += 1; }
int main() {
  int a = 0;
  add_one(a); // Not clear that a may be modified
  add_one(&a); // 'a' is clearly being passed destructively
}

使用指针,发生的事情总是(更)明显,因此对于 API 等,清晰度是一个大问题,指针不是比引用更合适吗?这是否意味着仅应在必要时使用引用(例如 operator++)?其中之一是否存在性能问题?

编辑(已过时)

除了允许 NULL 值和处理原始数组之外,似乎选择取决于个人喜好。我已接受下面引用 Google 的 C++ 风格指南的答案,正如它们所呈现的那样认为“引用可能会令人困惑,因为它们具有值语法但具有指针语义。”。

由于清理不应该为 NULL 的指针参数需要额外的工作(例如 add_one(0) 将调用指针版本并在运行时中断),从可维护性的角度来看,在以下位置使用引用是有意义的:一个对象必须存在,尽管失去语法清晰度是一种耻辱。

I understand the syntax and general semantics of pointers versus references, but how should I decide when it is more-or-less appropriate to use references or pointers in an API?

Naturally some situations need one or the other (operator++ needs a reference argument), but in general I'm finding I prefer to use pointers (and const pointers) as the syntax is clear that the variables are being passed destructively.

E.g. in the following code:

void add_one(int& n) { n += 1; }
void add_one(int* const n) { *n += 1; }
int main() {
  int a = 0;
  add_one(a); // Not clear that a may be modified
  add_one(&a); // 'a' is clearly being passed destructively
}

With the pointer, it's always (more) obvious what's going on, so for APIs and the like where clarity is a big concern are pointers not more appropriate than references? Does that mean references should only be used when necessary (e.g. operator++)? Are there any performance concerns with one or the other?

EDIT (OUTDATED)

Besides allowing NULL values and dealing with raw arrays, it seems the choice comes down to personal preference. I've accepted the answer below that references Google's C++ Style Guide, as they present the view that "References can be confusing, as they have value syntax but pointer semantics.".

Due to the additional work required to sanitise pointer arguments that should not be NULL (e.g. add_one(0) will call the pointer version and break during runtime), it makes sense from a maintainability perspective to use references where an object MUST be present, though it is a shame to lose the syntactic clarity.

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

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

发布评论

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

评论(17

蹲在坟头点根烟 2024-12-06 12:41:59

尽可能使用引用,并在必要时使用指针。

避免使用指针,除非你不能。

原因是,与任何其他构造相比,指针使事情更难以遵循/阅读、更不安全且危险得多。

因此,经验法则是只有在没有其他选择的情况下才使用指针。

例如,当函数在某些情况下可以返回 nullptr 并且假设它会返回时,返回指向对象的指针是一个有效的选项。也就是说,更好的选择是使用类似于 std::Optional< /code> (需要 C++17;在此之前,有 boost::可选)。

另一个例子是使用指向原始内存的指针来进行特定的内存操作。它应该隐藏并本地化在代码的非常狭窄的部分,以帮助限制整个代码库的危险部分。

在您的示例中,使用指针作为参数是没有意义的,因为:

  1. 如果您提供 nullptr 作为参数,您将进入未定义行为领域;
  2. 引用属性版本不允许(没有易于发现的技巧)1的问题。
  3. 引用属性版本对于用户来说更容易理解:您必须提供一个有效的对象,而不是可能为空的对象。

如果函数的行为必须在有或没有给定对象的情况下工作,那么使用指针作为属性建议您可以传递 nullptr 作为参数,这对于函数来说没问题。这是用户和实现之间的一种合同。

Use references wherever you can, and pointers wherever you must.

Avoid pointers until you can't.

The reason is that pointers make things harder to follow/read, less safe and far more dangerous manipulations than any other constructs.

So the rule of thumb is to use pointers only if there is no other choice.

For example, returning a pointer to an object is a valid option when the function can return nullptr in some cases and it is assumed it will. That said, a better option would be to use something similar to std::optional (requires C++17; before that, there's boost::optional).

Another example is to use pointers to raw memory for specific memory manipulations. That should be hidden and localized in very narrow parts of the code, to help limit the dangerous parts of the whole code base.

In your example, there is no point in using a pointer as an argument because:

  1. if you provide nullptr as the argument, you're going in undefined-behaviour-land;
  2. the reference attribute version doesn't allow (without easy-to-spot tricks) the problem with 1.
  3. the reference attribute version is simpler to understand for the user: you have to provide a valid object, not something that could be null.

If the behaviour of the function would have to work with or without a given object, then using a pointer as an attribute suggests that you can pass nullptr as the argument and it is fine for the function. That's kind of a contract between the user and the implementation.

遇见了你 2024-12-06 12:41:59

性能完全相同,因为引用在内部实现为指针。因此您无需担心这一点。

关于何时使用引用和指针,没有普遍接受的约定。在某些情况下,您必须返回或接受引用(例如复制构造函数),但除此之外,您可以自由地按照您的意愿进行操作。我遇到的一个相当常见的约定是,当参数必须引用现有对象时使用引用,而当 NULL 值可以时使用指针。

一些编码约定(例如 Google 的)规定应始终使用指针或 const 引用,因为引用有一些不清楚的语法:它们有引用行为但有值语法。

The performances are exactly the same, as references are implemented internally as pointers. Thus you do not need to worry about that.

There is no generally accepted convention regarding when to use references and pointers. In a few cases you have to return or accept references (copy constructor, for instance), but other than that you are free to do as you wish. A rather common convention I've encountered is to use references when the parameter must refer an existing object and pointers when a NULL value is ok.

Some coding convention (like Google's) prescribe that one should always use pointers, or const references, because references have a bit of unclear-syntax: they have reference behaviour but value syntax.

无戏配角 2024-12-06 12:41:59

来自 C++ FAQ Lite -

可以时使用引用,必要时使用指针。

当你不需要时,引用通常比指针更受欢迎
“重新就座”。这通常意味着参考文献在
类的公共接口。参考文献通常出现在皮肤上
一个对象,以及内部的指针。

上面的例外是函数的参数或返回值
值需要一个“哨兵”引用——一个不引用的引用
到一个物体。这通常最好通过返回/获取指针来完成,
并赋予 NULL 指针特殊的意义(引用必须
始终为对象别名,而不是取消引用的 NULL 指针)。

注意:老 C 程序员有时不喜欢引用,因为
它们提供调用者中不明确的引用语义
代码。然而,经过一些 C++ 经验之后,人们很快意识到这是
信息隐藏的一种形式,它是一种资产而不是一种
责任。例如,程序员应该用该语言编写代码
问题而不是机器的语言。

From C++ FAQ Lite -

Use references when you can, and pointers when you have to.

References are usually preferred over pointers whenever you don't need
"reseating". This usually means that references are most useful in a
class's public interface. References typically appear on the skin of
an object, and pointers on the inside.

The exception to the above is where a function's parameter or return
value needs a "sentinel" reference — a reference that does not refer
to an object. This is usually best done by returning/taking a pointer,
and giving the NULL pointer this special significance (references must
always alias objects, not a dereferenced NULL pointer).

Note: Old line C programmers sometimes don't like references since
they provide reference semantics that isn't explicit in the caller's
code. After some C++ experience, however, one quickly realizes this is
a form of information hiding, which is an asset rather than a
liability. E.g., programmers should write code in the language of the
problem rather than the language of the machine.

鯉魚旗 2024-12-06 12:41:59

我的经验法则是:

  • 对传出或输入/输出参数使用指针。所以可以看出这个值是要改变的。 (必须使用 &
  • 如果 NULL 参数是可接受的值,则使用指针。 (如果它是传入参数,请确保它是 const
  • 如果传入参数不能为 NULL 并且不是原始类型 (const T&),请使用传入参数的引用。
  • 返回新创建的对象时使用指针或智能指针。
  • 使用指针或智能指针作为结构或类成员而不是引用。
  • 使用别名引用(例如int ¤t = someArray[i]

无论您使用哪一种,如果函数及其参数的含义不明显,请不要忘记记录它们。

My rule of thumb is:

  • Use pointers for outgoing or in/out parameters. So it can be seen that the value is going to be changed. (You must use &)
  • Use pointers if NULL parameter is acceptable value. (Make sure it's const if it's an incoming parameter)
  • Use references for incoming parameter if it cannot be NULL and is not a primitive type (const T&).
  • Use pointers or smart pointers when returning a newly created object.
  • Use pointers or smart pointers as struct or class members instead of references.
  • Use references for aliasing (eg. int ¤t = someArray[i])

Regardless which one you use, don't forget to document your functions and the meaning of their parameters if they are not obvious.

云柯 2024-12-06 12:41:59

免责声明:除了引用不能为 NULL 也不能“反弹”(意味着不能更改它们的别名的对象)这一事实之外,这实际上取决于品味问题,所以我不会说“这样更好”。

也就是说,我不同意您在帖子中的最后一个声明,因为我认为代码不会因为引用而失去清晰度。在您的示例中,

add_one(&a);

可能会更清楚,

add_one(a);

因为您知道 a 的值很可能会发生变化。但另一方面,函数的签名

void add_one(int* const n);

也有些不清楚:n 是单个整数还是数组?有时您只能访问(文档记录很差)标头,并且诸如此类的签名

foo(int* const a, int b);

乍一看并不容易解释。

恕我直言,当不需要(重新)分配或重新绑定(在前面解释的意义上)时,引用与指针一样好。此外,如果开发人员仅使用数组指针,则函数签名就不那么模糊了。更不用说运算符语法通过引用更具可读性。

Disclaimer: other than the fact that references cannot be NULL nor "rebound" (meaning thay can't change the object they're the alias of), it really comes down to a matter of taste, so I'm not going to say "this is better".

That said, I disagree with your last statement in the post, in that I don't think the code loses clarity with references. In your example,

add_one(&a);

might be clearer than

add_one(a);

since you know that most likely the value of a is going to change. On the other hand though, the signature of the function

void add_one(int* const n);

is somewhat not clear either: is n going to be a single integer or an array? Sometimes you only have access to (poorly documentated) headers, and signatures like

foo(int* const a, int b);

are not easy to interpret at first sight.

Imho, references are as good as pointers when no (re)allocation nor rebinding (in the sense explained before) is needed. Moreover, if a developer only uses pointers for arrays, functions signatures are somewhat less ambiguous. Not to mention the fact that operators syntax is way more readable with references.

寄离 2024-12-06 12:41:59

就像其他人已经回答的那样:始终使用引用,除非 NULL/nullptr 的变量确实是有效状态。

约翰·卡马克对此主题的观点是相似的:

NULL 指针是 C/C++ 中最大的问题,至少在我们的代码中是这样。将单个值同时用作标志和地址会导致数量惊人的致命问题。只要有可能,C++ 引用应该优先于指针;虽然引用“实际上”只是一个指针,但它具有非 NULL 的隐式契约。当指针转换为引用时执行 NULL 检查,然后您可以忽略此问题。

http://www.altdevblogaday.com/2011/12/24/ static-code-analysis/

编辑 2012-03-13

用户 布雷特·库恩斯正确地评论:

C++11 标准已最终确定。我认为是时候在这个线程中提到大多数代码应该在引用、shared_ptr 和 unique_ptr 的组合下表现得非常好。

确实如此,但即使用智能指针替换原始指针,问题仍然存在。

例如,std::unique_ptrstd::shared_ptr 都可以通过其默认构造函数构造为“空”指针:

...意味着使用它们而不需要验证它们不为空可能会导致崩溃,这正是 J. Carmack 讨论的重点。

然后,我们遇到了一个有趣的问题“我们如何将智能指针作为函数参数传递?”

乔恩答案 对于问题 C++ - 将引用传递给boost::shared_ptr,并且以下注释表明,即使如此,通过复制或通过引用传递智能指针并不像人们希望的那样清晰(我默认情况下喜欢“通过引用”,但是我可能是错的)。

Like others already answered: Always use references, unless the variable being NULL/nullptr is really a valid state.

John Carmack's viewpoint on the subject is similar:

NULL pointers are the biggest problem in C/C++, at least in our code. The dual use of a single value as both a flag and an address causes an incredible number of fatal issues. C++ references should be favored over pointers whenever possible; while a reference is “really” just a pointer, it has the implicit contract of being not-NULL. Perform NULL checks when pointers are turned into references, then you can ignore the issue thereafter.

http://www.altdevblogaday.com/2011/12/24/static-code-analysis/

Edit 2012-03-13

User Bret Kuhns rightly remarks:

The C++11 standard has been finalized. I think it's time in this thread to mention that most code should do perfectly fine with a combination of references, shared_ptr, and unique_ptr.

True enough, but the question still remains, even when replacing raw pointers with smart pointers.

For example, both std::unique_ptr and std::shared_ptr can be constructed as "empty" pointers through their default constructor:

... meaning that using them without verifying they are not empty risks a crash, which is exactly what J. Carmack's discussion is all about.

And then, we have the amusing problem of "how do we pass a smart pointer as a function parameter?"

Jon's answer for the question C++ - passing references to boost::shared_ptr, and the following comments show that even then, passing a smart pointer by copy or by reference is not as clear cut as one would like (I favor myself the "by-reference" by default, but I could be wrong).

葬花如无物 2024-12-06 12:41:59

这不是品味问题。以下是一些明确的规则。

如果您想在声明的范围内引用静态声明的变量,请使用 C++ 引用,这将是完全安全的。这同样适用于静态声明的智能指针。通过引用传递参数是这种用法的一个示例。

如果您想引用比声明范围更宽的范围内的任何内容,那么您应该使用引用计数智能指针,以确保它完全安全。

为了语法方便,您可以使用引用来引用集合中的元素,但这并不安全;该元素可以随时删除。

为了安全地保存对集合元素的引用,您必须使用引用计数智能指针。

It is not a matter of taste. Here are some definitive rules.

If you want to refer to a statically declared variable within the scope in which it was declared then use a C++ reference, and it will be perfectly safe. The same applies to a statically declared smart pointer. Passing parameters by reference is an example of this usage.

If you want to refer to anything from a scope that is wider than the scope in which it is declared then you should use a reference counted smart pointer for it to be perfectly safe.

You can refer to an element of a collection with a reference for syntactic convenience, but it is not safe; the element can be deleted at anytime.

To safely hold a reference to an element of a collection you must use a reference counted smart pointer.

孤者何惧 2024-12-06 12:41:59

尽可能使用引用”规则存在问题,如果您想保留引用以供进一步使用,则会出现此问题。为了用示例来说明这一点,假设您有以下课程。

class SimCard
{
    public:
        explicit SimCard(int id):
            m_id(id)
        {
        }

        int getId() const
        {
            return m_id;
        }

    private:
        int m_id;
};

class RefPhone
{
    public:
        explicit RefPhone(const SimCard & card):
            m_card(card)
        {
        }

        int getSimId()
        {
            return m_card.getId();
        }

    private:
        const SimCard & m_card;
};

乍一看,在 RefPhone(const SimCard & card) 构造函数中通过引用传递参数似乎是个好主意,因为它可以防止将错误/空指针传递给构造函数。它以某种方式鼓励在堆栈上分配变量并从 RAII 中受益。

PtrPhone nullPhone(0);  //this will not happen that easily
SimCard * cardPtr = new SimCard(666);  //evil pointer
delete cardPtr;  //muahaha
PtrPhone uninitPhone(cardPtr);  //this will not happen that easily

但随后,临时的事情就会摧毁你的幸福世界。

RefPhone tempPhone(SimCard(666));   //evil temporary
//function referring to destroyed object
tempPhone.getSimId();    //this can happen

因此,如果您盲目地坚持引用,您就会牺牲传递无效指针的可能性来存储对已销毁对象的引用的可能性,这基本上具有相同的效果。

编辑:请注意,我坚持“尽可能使用引用,必须使用指针。除非不能,否则避免使用指针”。来自最受支持和接受的答案(其他答案也表明如此)。虽然这应该是显而易见的,但例子并不表明引用本身是不好的。然而,它们可能会被滥用,就像指针一样,它们可能会给代码带来威胁。


指针和引用之间存在以下差异。

  1. 当谈到传递变量时,按引用传递看起来像按值传递,但具有指针语义(就像指针一样)。
  2. 引用不能直接初始化为0(空)。
  3. Reference(引用,未引用的对象)不可修改(相当于“*const”指针)。
  4. const 引用可以接受临时参数。
  5. 延长了临时对象的生命周期

本地 const引用 考虑到我目前的规则如下。

  • 对将在函数作用域内本地使用的参数使用引用。
  • 当 0(空)是可接受的参数值或者需要存储参数以供进一步使用时,请使用指针。如果 0 (null) 可以接受,我将在参数中添加“_n”后缀,使用受保护的指针(如 Qt 中的 QPointer)或只是记录它。您还可以使用智能指针。 与普通指针相比,您必须更加小心地使用共享指针(否则您可能会因设计而导致内存泄漏和责任混乱)。

There is problem with "use references wherever possible" rule and it arises if you want to keep reference for further use. To illustrate this with example, imagine you have following classes.

class SimCard
{
    public:
        explicit SimCard(int id):
            m_id(id)
        {
        }

        int getId() const
        {
            return m_id;
        }

    private:
        int m_id;
};

class RefPhone
{
    public:
        explicit RefPhone(const SimCard & card):
            m_card(card)
        {
        }

        int getSimId()
        {
            return m_card.getId();
        }

    private:
        const SimCard & m_card;
};

At first it may seem to be a good idea to have parameter in RefPhone(const SimCard & card) constructor passed by a reference, because it prevents passing wrong/null pointers to the constructor. It somehow encourages allocation of variables on stack and taking benefits from RAII.

PtrPhone nullPhone(0);  //this will not happen that easily
SimCard * cardPtr = new SimCard(666);  //evil pointer
delete cardPtr;  //muahaha
PtrPhone uninitPhone(cardPtr);  //this will not happen that easily

But then temporaries come to destroy your happy world.

RefPhone tempPhone(SimCard(666));   //evil temporary
//function referring to destroyed object
tempPhone.getSimId();    //this can happen

So if you blindly stick to references you trade off possibility of passing invalid pointers for the possibility of storing references to destroyed objects, which has basically same effect.

edit: Note that I sticked to the rule "Use reference wherever you can, pointers wherever you must. Avoid pointers until you can't." from the most upvoted and accepted answer (other answers also suggest so). Though it should be obvious, example is not to show that references as such are bad. They can be misused however, just like pointers and they can bring their own threats to the code.


There are following differences between pointers and references.

  1. When it comes to passing variables, pass by reference looks like pass by value, but has pointer semantics (acts like pointer).
  2. Reference can not be directly initialized to 0 (null).
  3. Reference (reference, not referenced object) can not be modified (equivalent to "* const" pointer).
  4. const reference can accept temporary parameter.
  5. Local const references prolong the lifetime of temporary objects

Taking those into account my current rules are as follows.

  • Use references for parameters that will be used locally within a function scope.
  • Use pointers when 0 (null) is acceptable parameter value or you need to store parameter for further use. If 0 (null) is acceptable I am adding "_n" suffix to parameter, use guarded pointer (like QPointer in Qt) or just document it. You can also use smart pointers. You have to be even more careful with shared pointers than with normal pointers (otherwise you can end up with by design memory leaks and responsibility mess).
番薯 2024-12-06 12:41:59

任何性能差异都非常小,以至于没有理由使用不太明确的方法。

首先,没有提到引用通常更优越的一种情况是 const 引用。对于非简单类型,传递 const 引用 可以避免创建临时变量,也不会导致您担心的混乱(因为该值没有被修改)。在这里,强迫一个人传递指针会导致您担心的混乱,因为看到地址被获取并传递给函数可能会让您认为值发生了变化。

无论如何,我基本上同意你的观点。当函数正在做的事情不是很明显时,我不喜欢函数通过引用来修改它们的值。在这种情况下我也更喜欢使用指针。

当您需要返回复杂类型的值时,我倾向于更喜欢引用。例如:

bool GetFooArray(array &foo); // my preference
bool GetFooArray(array *foo); // alternative

在这里,函数名称清楚地表明您正在数组中获取信息。所以不存在混乱。

引用的主要优点是它们始终包含有效值,比指针更干净,并且支持多态性而不需要任何额外的语法。如果这些优点都不适用,则没有理由更喜欢引用而不是指针。

Any performance difference would be so small that it wouldn't justify using the approach that's less clear.

First, one case that wasn't mentioned where references are generally superior is const references. For non-simple types, passing a const reference avoids creating a temporary and doesn't cause the confusion you're concerned about (because the value isn't modified). Here, forcing a person to pass a pointer causes the very confusion you're worried about, as seeing the address taken and passed to a function might make you think the value changed.

In any event, I basically agree with you. I don't like functions taking references to modify their value when it's not very obvious that this is what the function is doing. I too prefer to use pointers in that case.

When you need to return a value in a complex type, I tend to prefer references. For example:

bool GetFooArray(array &foo); // my preference
bool GetFooArray(array *foo); // alternative

Here, the function name makes it clear that you're getting information back in an array. So there's no confusion.

The main advantages of references are that they always contain a valid value, are cleaner than pointers, and support polymorphism without needing any extra syntax. If none of these advantages apply, there is no reason to prefer a reference over a pointer.

王权女流氓 2024-12-06 12:41:59

复制自 wiki-

这样做的结果是,在许多实现中,通过引用对具有自动或静态生存期的变量进行操作,尽管在语法上与直接访问它类似,但可能涉及成本高昂的隐藏取消引用操作。引用是 C++ 语法上有争议的特性,因为它们掩盖了标识符的间接级别。也就是说,与指针通常在语法上很突出的 C 代码不同,在一大块 C++ 代码中,如果正在访问的对象被定义为局部变量或全局变量,或者它是否是对的引用(隐式指针),可能不会立即显而易见。某个其他位置,特别是当代码混合引用和指针时。这方面可能会使写得不好的 C++ 代码更难阅读和调试(请参阅别名)。

我 100% 同意这一点,这就是为什么我认为只有在有充分理由时才应该使用参考文献。

Copied from wiki-

A consequence of this is that in many implementations, operating on a variable with automatic or static lifetime through a reference, although syntactically similar to accessing it directly, can involve hidden dereference operations that are costly. References are a syntactically controversial feature of C++ because they obscure an identifier's level of indirection; that is, unlike C code where pointers usually stand out syntactically, in a large block of C++ code it may not be immediately obvious if the object being accessed is defined as a local or global variable or whether it is a reference (implicit pointer) to some other location, especially if the code mixes references and pointers. This aspect can make poorly written C++ code harder to read and debug (see Aliasing).

I agree 100% with this, and this is why I believe that you should only use a reference when you a have very good reason for doing so.

迎风吟唱 2024-12-06 12:41:59

要记住的要点:

  1. 指针可以为 NULL,引用不能为 NULL

  2. 引用更容易使用,当我们不想改变值而只需要函数中的引用时,可以使用const作为引用。

  3. 指针与 * 一起使用,而引用与 & 一起使用。

  4. 当需要进行指针算术运算时使用指针。

  5. 您可以拥有指向 void 类型的指针 int a=5; void *p = &a; 但不能拥有对 void 类型的引用。

指针与引用

void fun(int *a)
{
    cout<<a<<'\n'; // address of a = 0x7fff79f83eac
    cout<<*a<<'\n'; // value at a = 5
    cout<<a+1<<'\n'; // address of a increment by 4 bytes(int) = 0x7fff79f83eb0
    cout<<*(a+1)<<'\n'; // value here is by default = 0
}
void fun(int &a)
{
    cout<<a<<'\n'; // reference of original a passed a = 5
}
int a=5;
fun(&a);
fun(a);

判断何时使用什么

指针:用于数组、链接列表、树实现和指针算术。

参考:在函数参数和返回类型中。

Points to keep in mind:

  1. Pointers can be NULL, references cannot be NULL.

  2. References are easier to use, const can be used for a reference when we don't want to change value and just need a reference in a function.

  3. Pointer used with a * while references used with a &.

  4. Use pointers when pointer arithmetic operation are required.

  5. You can have pointers to a void type int a=5; void *p = &a; but cannot have a reference to a void type.

Pointer Vs Reference

void fun(int *a)
{
    cout<<a<<'\n'; // address of a = 0x7fff79f83eac
    cout<<*a<<'\n'; // value at a = 5
    cout<<a+1<<'\n'; // address of a increment by 4 bytes(int) = 0x7fff79f83eb0
    cout<<*(a+1)<<'\n'; // value here is by default = 0
}
void fun(int &a)
{
    cout<<a<<'\n'; // reference of original a passed a = 5
}
int a=5;
fun(&a);
fun(a);

Verdict when to use what

Pointer: For array, linklist, tree implementations and pointer arithmetic.

Reference: In function parameters and return types.

作死小能手 2024-12-06 12:41:59

以下是一些准则。

函数使用传递的数据而不对其进行修改:

  1. 如果数据对象很小,例如内置数据类型或小型结构,则按值传递。

  2. 如果数据对象是数组,请使用指针,因为这是您唯一的选择。使指针成为指向 const 的指针。

  3. 如果数据对象是一个大小合适的结构,请使用 const 指针或 const
    提高程序效率的参考。您节省了所需的时间和空间
    复制结构或类设计。使指针或引用常量。

  4. 如果数据对象是类对象,则使用const引用。类设计的语义常常需要使用引用,这也是C++添加的主要原因
    此功能。因此,传递类对象参数的标准方法是通过引用。

函数修改调用函数中的数据:

1.如果数据对象是内置数据类型,则使用指针。如果你发现代码
就像fixit(&x)一样,其中x是一个int,很明显这个函数打算修改x。

2.如果数据对象是数组,则使用唯一的选择:指针。

3.如果数据对象是结构体,则使用引用或指针。

4.如果数据对象是类对象,则使用引用。

当然,这些只是指导方针,可能有不同的原因
选择。例如,cin 使用基本类型的引用,以便您可以使用 cin >> n
而不是 cin >> &n.

The following are some guidelines.

A function uses passed data without modifying it:

  1. If the data object is small, such as a built-in data type or a small structure, pass it by value.

  2. If the data object is an array, use a pointer because that’s your only choice. Make the pointer a pointer to const.

  3. If the data object is a good-sized structure, use a const pointer or a const
    reference to increase program efficiency.You save the time and space needed to
    copy a structure or a class design. Make the pointer or reference const.

  4. If the data object is a class object, use a const reference.The semantics of class design often require using a reference, which is the main reason C++ added
    this feature.Thus, the standard way to pass class object arguments is by reference.

A function modifies data in the calling function:

1.If the data object is a built-in data type, use a pointer. If you spot code
like fixit(&x), where x is an int, it’s pretty clear that this function intends to modify x.

2.If the data object is an array, use your only choice: a pointer.

3.If the data object is a structure, use a reference or a pointer.

4.If the data object is a class object, use a reference.

Of course, these are just guidelines, and there might be reasons for making different
choices. For example, cin uses references for basic types so that you can use cin >> n
instead of cin >> &n.

情定在深秋 2024-12-06 12:41:59

您正确编写的示例应该类似于

void add_one(int& n) { n += 1; }
void add_one(int* const n)
{
  if (n)
    *n += 1;
}

这就是为什么如果可能的话,引用是更好的选择
...

Your properly written example should look like

void add_one(int& n) { n += 1; }
void add_one(int* const n)
{
  if (n)
    *n += 1;
}

That's why references are preferable if possible
...

总以为 2024-12-06 12:41:59

参考文献更清晰、更易于使用,并且可以更好地隐藏信息。
但是,引用不能重新分配。
如果需要先指向一个对象,然后再指向另一个对象,则必须使用指针。引用不能为 null,因此如果存在相关对象可能为 null 的可能性,则不得使用引用。您必须使用指针。
如果您想自己处理对象操作,即如果您想在堆上而不是堆栈上为对象分配内存空间,则必须使用指针

int *pInt = new int; // allocates *pInt on the Heap

References are cleaner and easier to use, and they do a better job of hiding information.
References cannot be reassigned, however.
If you need to point first to one object and then to another, you must use a pointer. References cannot be null, so if any chance exists that the object in question might be null, you must not use a reference. You must use a pointer.
If you want to handle object manipulation on your own i.e if you want to allocate memory space for an object on the Heap rather on the Stack you must use Pointer

int *pInt = new int; // allocates *pInt on the Heap
悍妇囚夫 2024-12-06 12:41:59

在我的实践中,我个人确定了一个简单的规则 - 对可复制/可移动的原语和值使用引用,对具有长生命周期的对象使用指针。

对于 Node 示例,我肯定会使用

AddChild(Node* pNode);

In my practice I personally settled down with one simple rule - Use references for primitives and values that are copyable/movable and pointers for objects with long life cycle.

For Node example I would definitely use

AddChild(Node* pNode);
恬淡成诗 2024-12-06 12:41:59

只是投入我的一角钱。我刚刚进行了测试。这是一个偷偷摸摸的人。与使用引用相比,我只是让 g++ 使用指针创建同一小程序的汇编文件。
当查看输出时,它们完全相同。除了符号命名之外。所以看看性能(在一个简单的例子中)是没有问题的。

现在讨论指针与引用的主题。恕我直言,我认为清晰度高于一切。一旦我读到隐性行为,我的脚趾就开始卷曲。我同意引用不能为 NULL 是很好的隐式行为。

取消引用 NULL 指针不是问题。它会让你的应用程序崩溃并且很容易调试。一个更大的问题是未初始化的指针包含无效值。这很可能会导致内存损坏,从而导致没有明确来源的未定义行为。

这就是我认为引用比指针安全得多的地方。我同意之前的说法,即接口(应该清楚地记录下来,请参阅合同设计,Bertrand Meyer)定义函数参数的结果。现在考虑到这一切我的偏好去
尽可能使用参考文献。

Just putting my dime in. I just performed a test. A sneeky one at that. I just let g++ create the assembly files of the same mini-program using pointers compared to using references.
When looking at the output they are exactly the same. Other than the symbolnaming. So looking at performance (in a simple example) there is no issue.

Now on the topic of pointers vs references. IMHO I think clearity stands above all. As soon as I read implicit behaviour my toes start to curl. I agree that it is nice implicit behaviour that a reference cannot be NULL.

Dereferencing a NULL pointer is not the problem. it will crash your application and will be easy to debug. A bigger problem is uninitialized pointers containing invalid values. This will most likely result in memory corruption causing undefined behaviour without a clear origin.

This is where I think references are much safer than pointers. And I agree with a previous statement, that the interface (which should be clearly documented, see design by contract, Bertrand Meyer) defines the result of the parameters to a function. Now taking this all into consideration my preferences go to
using references wherever/whenever possible.

长伴 2024-12-06 12:41:59

对于指针,您需要它们指向某些内容,因此指针会占用内存空间。

例如,采用整数指针的函数将不会采用整数变量。因此,您需要首先创建一个指针以传递给函数。

至于参考,不会耗费内存。您有一个整型变量,可以将其作为引用变量传递。就是这样。您不需要专门为其创建引用变量。

For pointers, you need them to point to something, so pointers cost memory space.

For example a function that takes an integer pointer will not take the integer variable. So you will need to create a pointer for that first to pass on to the function.

As for a reference, it will not cost memory. You have an integer variable, and you can pass it as a reference variable. That's it. You don't need to create a reference variable specially for it.

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