【问题标题】:When to use references vs. pointers何时使用引用与指针
【发布时间】:2011-10-26 20:45:37
【问题描述】:

我了解指针与引用的语法和一般语义,但我应该如何决定何时在 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's C++ Style Guide 的答案,因为它们提出了“引用可能令人困惑,因为它们具有值语法但指针语义”的观点。

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

【问题讨论】:

  • 您似乎已经决定何时使用哪一个。就个人而言,我更喜欢传入我正在操作的对象,无论我是否正在修改它。如果一个函数接受一个指针,这告诉我它正在作用于指针,即将它们用作数组中的迭代器。
  • @Schnommus:很公平,我主要使用 TextMate。不过,我认为最好一目了然。
  • add_one(a); 不清楚a 会被修改怎么办?它在代码中说:add one.
  • @connec:Google C++ 风格指南并不是一个好的 C++ 风格指南。它是使用 Google 的旧 C++ 代码库的风格指南(即对他们的东西有好处)。接受基于此的答案对任何人都没有帮助。只需阅读您的 cmets 和解释,您就已经带着既定的观点提出了这个问题,并且只是在寻找其他人来确认您的观点。因此,您的问题和答案都基于您想要/期望听到的内容。
  • 这只是通过命名方法addOneTo(...)来解决的。如果这不是您想要做的,只需查看声明即可。

标签: c++ pointers reference


【解决方案1】:

尽可能使用参考,在需要的地方使用指针。

避免使用指针,直到你不能。

原因在于,与任何其他构造相比,指针使事情更难理解/阅读、更不安全且更危险的操作。

所以经验法则是只有在别无选择时才使用指针。

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

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

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

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

如果函数的行为必须在有或没有给定对象的情况下工作,那么使用指针作为属性表明您可以将nullptr 作为参数传递,这对函数来说很好。这是用户和实现之间的一种契约。

【讨论】:

  • 我不确定指针是否会使任何东西更难阅读?这是一个相当简单的概念,并且可以清楚地说明何时可能会修改某些内容。如果有什么我会说在没有迹象表明发生了什么的情况下更难阅读,为什么add_one(a) 不返回结果,而不是通过引用设置它?
  • @connec:如果add_one(a) 令人困惑,那是因为它的命名不正确。 add_one(&a) 会有同样的困惑,只是现在你可能会增加指针而不是对象。 add_one_inplace(a) 会避免所有的混乱。
  • 有一点,引用可以引用可以像指针一样容易消失的内存。所以它们不一定比指针更安全。持久化和传递引用可能和指针一样危险。
  • @Klaim 我的意思是原始指针。我的意思是 C++ 有指针,NULLnullptr,它有它们是有原因的。给出“从不使用指针”和/或“从不使用 NULL,总是使用boost::optional”不是一个经过深思熟虑甚至不现实的建议。这简直是​​疯了。不要误会我的意思,在 C++ 中比在 C 中更不需要原始指针,但它们仍然很有用,它们并不像某些 C++ 人喜欢声称的那样“危险”(这也很夸张),再说一遍:当使用指针和return nullptr; 来指示缺失值更容易时......为什么要导入整个Boost?
  • @NicolBolas hmmmm add_one_inplace(a) IMO 看起来并不好。如果你有更多的参数怎么办? add_and_check_inplace_inplace_notinplace_notinplace(a, b, c, d)?
【解决方案2】:

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

关于何时使用引用和指针没有普遍接受的约定。在少数情况下,您必须返回或接受引用(例如复制构造函数),但除此之外,您可以随意做任何事情。我遇到的一个相当常见的约定是,当参数必须引用现有对象时使用引用,而当 NULL 值可以时使用指针。

一些编码约定(如Google's)规定应该始终使用指针或常量引用,因为引用有一些不明确的语法:它们有引用行为但有值语法。

【讨论】:

  • 只是补充一点,谷歌的style guide says 函数的输入参数应该是常量引用,输出应该是指针。我喜欢这样,因为当您阅读函数签名时,它会非常清楚什么是输入,什么是输出。
  • @Dan:Google 风格指南适用于 Google 的旧代码,不应该用于现代编码。事实上,对于一个新项目来说,这是一种相当糟糕的编码风格。
  • @connec:我这样说吧:null 是一个完全有效的指针值。任何有指针的地方,我都可以给它 null 值。所以你的add_one 的第二个版本损坏了add_one(0); // passing a perfectly valid pointer value,kaboom。您需要检查它是否为空。有些人会反驳:“好吧,我只是记录下我的函数不适用于 null”。没关系,但是这样您就违背了问题的目的:如果您要查看文档以查看 null 是否可以,您还会看到函数声明
  • 如果它是一个参考,你会看到是这样的。但是这样的反驳没有抓住重点:引用强制在语言级别它引用现有对象,并且不可能为空,而指针没有这样的限制。我认为很明显,语言级别的执行比文档级别的执行更强大,更不容易出错。有些人会试图反驳说:“看,空引用:int& i = *((int*)0);。这不是一个有效的反驳。前面代码中的问题在于指针的使用,而不是引用. 引用永远不会为空,句号。
  • 您好,我看到 cmets 中缺少语言律师,所以让我补救一下:引用通常由指针实现,但标准没有这样说。使用其他机制的实现将是 100% 的投诉。
【解决方案3】:

来自C++ FAQ Lite -

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

当您不需要时,通常首选引用而不是指针 “重新安置”。这通常意味着引用在 类的公共接口。参考文献通常出现在 一个对象,内部有指针。

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

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

【讨论】:

  • 我想您可能会争辩说,如果您使用的是 API,您应该熟悉它的作用并知道传递的参数是否被修改......需要考虑,但我发现自己同意 C 程序员的观点(尽管我自己的 C 经验很少)。我要补充的是,更清晰的语法对程序员和机器都有好处。
  • @connec:C 程序员肯定有它适合他们的语言。但是不要犯把 C++ 当作 C 的错误。它是一种完全不同的语言。如果你把 C++ 当作 C 来对待,你最终会写出同样被引用为 C with class(这不是 C++)的东西。
【解决方案4】:

我的经验法则是:

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

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

【讨论】:

    【解决方案5】:

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

    也就是说,我不同意您在帖子中的最后陈述,因为我认为代码不会因引用而变得清晰。在您的示例中,

    add_one(&a);
    

    可能比

    更清楚
    add_one(a);
    

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

    void add_one(int* const n);
    

    也有点不清楚:n 是单个整数还是数组?有时您只能访问(文档很少的)标头和签名,如

    foo(int* const a, int b);
    

    乍一看并不容易理解。

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

    【讨论】:

    • 感谢您清楚地展示了两种解决方案在何处获得和失去清晰度。我最初是在指针阵营,但这很有意义。
    【解决方案6】:

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

    John Carmack 在这个问题上的观点是相似的:

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

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

    编辑 2012-03-13

    用户Bret Kuhns 正确评论:

    C++11 标准已经定稿。我认为是时候在这个线程中提到大多数代码应该完美结合引用、shared_ptr 和 unique_ptr。

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

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

    ...意味着在不验证它们是否为空的情况下使用它们可能会导致崩溃,这正是 J. Carmack 讨论的全部内容。

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

    Jonanswer 用于问题 C++ - passing references to boost::shared_ptr,以下 cmets 表明,即便如此,通过复制或引用传递智能指针并不像人们希望的那样清晰(我赞成自己默认情况下是“by-reference”,但我可能是错的)。

    【讨论】:

    • C++11 标准已经定稿。我认为是时候在这个线程中提到大多数代码应该完美结合引用shared_ptrunique_ptr。所有权语义和输入/输出参数约定由这三个部分和 const'ness 的组合来处理。 C++ 中几乎不需要原始指针,除非处理遗留代码和非常优化的算法。使用它们的区域应尽可能封装,并将任何原始指针转换为语义上合适的“现代”等价物。
    • 很多时候智能指针不应该被传递,而是应该测试是否为空,然后通过引用传递它们包含的对象。您真正应该传递智能指针的唯一时间是当您转移 (unique_ptr) 或与另一个对象共享 (shared_ptr) 所有权时。
    • @povman:我完全同意:如果所有权不是接口的一部分(除非它即将被修改,否则不应该),那么我们不应该将智能指针传递为一个参数(或返回值)。当所有权是接口的一部分时,事情会变得有点复杂。例如,关于如何将 unique_ptr 作为参数传递的 Sutter/Meyers 辩论:通过复制 (Sutter) 还是通过 r 值引用 (Meyers)?反模式依赖于传递指向全局 shared_ptr 的指针,存在该指针无效的风险(解决方案是将智能指针复制到堆栈上)
    【解决方案7】:

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

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

    如果你想从一个比声明它的范围更宽的范围内引用任何东西,那么你应该使用一个引用计数的智能指针来保证它是完全安全的。

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

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

    【讨论】:

      【解决方案8】:

      任何性能差异都会非常小,以至于无法证明使用不太明确的方法是合理的。

      首先,没有提到引用通常更好的一个案例是const 引用。对于非简单类型,传递 const reference 可避免创建临时变量,并且不会引起您担心的混淆(因为未修改值)。在这里,强迫一个人传递一个指针会引起你担心的非常混乱,因为看到地址被获取并传递给一个函数可能会让你认为值改变了。

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

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

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

      这里,函数名称清楚地表明您正在以数组的形式获取信息。所以没有混淆。

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

      【讨论】:

        【解决方案9】:

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

        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
        

        因此,如果您盲目地坚持引用,您会在传递无效指针的可能性与存储对已破坏对象的引用的可能性之间进行权衡,这具有基本相同的效果。

        edit:请注意,我坚持“尽可能使用引用,必须使用指针。避免使用指针,直到不能使用”的规则。来自最受好评和接受的答案(其他答案也建议如此)。尽管应该很明显,但示例并不是要表明此类引用是不好的。然而,它们可能会被滥用,就像指针一样,它们会给代码带来自己的威胁。


        指针和引用有以下区别。

        1. 在传递变量时,按引用传递看起来像按值传递,但具有指针语义(类似于指针)。
        2. 无法将引用直接初始化为 0(空)。
        3. 引用(引用,未引用的对象)不能修改(相当于“* const”指针)。
        4. const 引用可以接受临时参数。
        5. Local const references prolong the lifetime of temporary objects

        考虑到这些,我目前的规则如下。

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

        【讨论】:

        • 您的示例的问题不是引用不安全,而是您依赖对象实例范围之外的东西来保持私有成员的活动。 const SimCard & m_card; 只是一个糟糕的代码。
        • @plamenko 我担心你不明白这个例子的目的。 const SimCard & m_card 是否正确取决于上下文。这篇文章中的信息不是引用是不安全的(如果努力的话,它们可能是不安全的)。信息是你不应该盲目地坚持“尽可能使用参考”的口头禅。示例是积极使用“尽可能使用引用”原则的结果。这应该很清楚。
        • 您的回答有两件事让我感到困扰,因为我认为这可能会误导试图了解更多有关此事的人。 1.帖子是单向的,很容易给人一种参考不好的印象。您只提供了一个如何不使用引用的示例。 2.你在你的例子中不清楚它有什么问题。是的,临时的会被破坏,但不是那行错误,而是类的实现。
        • 您几乎不应该拥有像const SimCard & m_card 这样的成员。如果你想高效地使用临时对象,请添加 explicit RefPhone(const SimCard&& card) 构造函数。
        • @plamenko 如果您无法通过一些基本的理解来阅读,那么您遇到的问题不仅仅是被我的帖子误导了。我不知道我怎么能更清楚。看第一句话。 “尽可能使用引用”的口头禅存在问题!在我的帖子中,您在哪里找到了引用不好的声明?在我的帖子末尾,您已经写了在哪里使用参考文献,那么您是如何得出这样的结论的?这不是问题的直接答案?
        【解决方案10】:

        复制自wiki-

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

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

        【讨论】:

        • 我在很大程度上也同意,但是我正在接受这样一种观点,即失去针对 NULL 指针的内置保护对于纯粹的句法问题来说代价有点太高了,尤其是 - 尽管更明确 - 指针语法无论如何都很难看。
        • 我想情况也是一个重要因素。我认为在当前代码库主要使用指针时尝试使用引用将是一个坏主意。如果您希望它们成为参考,那么它们如此隐含的事实可能就不那么重要了..
        【解决方案11】:

        注意事项:

        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);
        

        判断何时使用什么

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

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

        【讨论】:

        • 1.如果数组的大小是固定的,则不必使用指针来传递数组。 2. 传递span 比传递数组好。 3. 返回引用并不总是一个好主意。
        【解决方案12】:

        以下是一些准则。

        一个函数使用传递的数据而不修改它:

        1. 如果数据对象比较小,比如内置数据类型或者小型结构,就按值传递。

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

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

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

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

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

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

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

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

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

        【讨论】:

          【解决方案13】:

          您正确编写的示例应如下所示

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

          这就是为什么尽可能推荐参考 ...

          【讨论】:

            【解决方案14】:

            引用更简洁、更易于使用,并且在隐藏信息方面做得更好。 但是,不能重新分配引用。 如果您需要先指向一个对象,然后再指向另一个对象,则必须使用指针。引用不能为空,因此如果有任何可能存在相关对象可能为空的情况,则不得使用引用。您必须使用指针。 如果您想自己处理对象操作,即如果您想为堆上而不是堆栈上的对象分配内存空间,则必须使用指针

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

            【讨论】:

              【解决方案15】:

              在我的实践中,我个人采用了一条简单的规则——对可复制/可移动的基元和值使用引用,对生命周期长的对象使用指针。

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

              AddChild(Node* pNode);
              

              【讨论】:

                【解决方案16】:

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

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

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

                这是我认为引用比指针更安全的地方。我同意前面的说法,即接口(应该清楚地记录在案,参见按合同设计,Bertrand Meyer)定义了函数参数的结果。现在考虑到这一切,我的偏好去 尽可能/尽可能使用引用。

                【讨论】:

                  【解决方案17】:

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

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

                  作为参考,它不会消耗内存。您有一个整数变量,您可以将其作为参考变量传递。而已。你不需要专门为它创建一个引用变量。

                  【讨论】:

                  • 不。接受指针的函数不需要分配指针变量:您可以传递一个临时的&amp;address。如果引用是对象的成员,那么引用肯定会消耗内存,而且,所有现存的编译器实际上都将引用实现为地址,因此您在参数传递或取消引用方面也没有任何节省。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多