【问题标题】:When to pass by reference and when to pass by pointer in C++?在 C++ 中何时通过引用传递以及何时通过指针传递?
【发布时间】:2011-04-06 11:57:19
【问题描述】:

常见情况:

  1. 将 std::string 传递给函数 foo(std::string*) 或 foo(std::string&);
  2. 将 tr1::shared_ptr 传递给函数 foo(tr1::shared_ptr* ptr) 或 foo(tr1::shared_ptr& ptr);

一般来说,什么是好的做法。我总是感到困惑。起初,将所有内容作为引用传递似乎是一致的,但是不可能将 Literals 作为引用传递或将 NULL 作为引用传递。

同样,将所有内容都作为指针似乎很好,但是我不得不担心指针可能指向 NULL,并在该函数的开头检查这些条件。

你觉得下面这个sn-p好不好?

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <tr1/memory>
#include <algorithm>
using namespace std;
using namespace std::tr1;

int main(){
        map<string, shared_ptr<vector<string> > > adjacencyMap;
        vector<string>* myFriends = new vector<string>();
        myFriends->push_back(string("a"));
        myFriends->push_back(string("v"));
        myFriends->push_back(string("g"));
        adjacencyMap["s"] = shared_ptr<vector<string> >(myFriends);
        return 0;
}

谢谢 阿杰

【问题讨论】:

标签: c++


【解决方案1】:

我更喜欢

    map<string, shared_ptr<vector<string> > > adjacencyMap;
    shared_ptr<vector<string> > myFriends(new vector<string>());
    myFriends->push_back(string("a"));
    myFriends->push_back(string("v"));
    myFriends->push_back(string("g"));
    adjacencyMap["s"] = myFriends;
    return 0;

因为这可确保您的本地 var 处理是异常安全的。

不过,我真的不明白这如何解决您的问题,这是关于 ref 与 ptr 的优点。在您引用的两个示例中,我希望使用第二种(参考)形式。

【讨论】:

    【解决方案2】:

    您可以浏览http://www.cplusplus.com/forum/beginner/3958/ 了解一些见解。 也很有用:http://www.velocityreviews.com/forums/t284603-pointers-vs-references-a-question-on-style.html

    我想没有“正确”的答案。您需要根据项目的具体情况权衡每种方法的优缺点。

    我个人更喜欢参考资料,但我还是建议阅读这些帖子并思考一下。

    【讨论】:

      【解决方案3】:

      引用更容易正确。

      您是否对不使用 const 引用的文字有问题?您不能将临时(由文字产生)绑定到非常量引用,因为更改它没有任何意义。您可以将一个绑定到 const 引用。

      特别是,当将参数传递给函数时,函数不会更改它,并且它不是内置类型,请通过 const 引用传递。它的工作原理与按值传递非常相似,只是它不需要调用复制构造函数。

      指针很有用,因为它们具有可以测试的保证无效值。有时这无关紧要,有时却很重要。当然,通常不能通过指针传递文字,除非(在字符串文字的情况下)它已经是。

      一些编码标准说任何东西都不应该通过非常量引用传递,因为它在调用点没有提供参数可能被函数更改的指示。在这种情况下,您将需要通过指针传递。我不赞成这样做,特别是因为编程工具使获取函数签名变得越来越容易,因此您可以查看函数是否可能会更改参数。但是,在团队或企业中工作时,风格的一致性比任何单独的风格元素都更重要。

      【讨论】:

        【解决方案4】:

        作为一般经验法则,始终尝试通过引用 const 来传递参数。传递指针可能会导致所有权问题以及一系列其他细微错误的可能性。

        NULL 的目的是什么?指示无效的指针/对象。如果您要将无效对象传递给函数,那么您所要做的就是拥有一个检查对象有效性的方法。如:

        void myfunc(const obj& myobj)
        {
          if(myobj.valid())
            // DO SOMETHING
        }
        

        无论如何,您通常都希望通过值传递原始类型,因为开销很小。无论如何,那是您大部分时间都使用文字的时候。对于字符串,您应该尝试使用std::string,并尽可能远离const char* C 风格的字符串。当然,如果你必须使用 C 字符串,那么你别无选择,只能使用指针,但总而言之,引用应该是要走的路。

        哦,要真正做到异常安全,请尽量避免这种情况:

        vector<string>* myFriends = new vector<string>();
        ...
        adjacencyMap["s"] = shared_ptr<vector<string> >(myFriends);
        

        改为:

        shared_ptr<vector<string> > myFriends(new vector<string>());
        

        查看 RAII 和异常安全性,了解为什么这是首选方法。

        【讨论】:

          【解决方案5】:

          在我之前的工作中,我们有一条规则,即实际上从不使用纯引用。相反,我们同意:

          • 按值传递(用于廉价复制对象、所有原语、小值类型、std::string、非常小的或引用的字符串)
          • 通过const 引用(用于对大对象的只读访问)
          • 如果需要读写访问,则通过指针传递

          如果每个人都遵循这些规则,您可以假设传递给函数的参数不会被修改,除非它们的地址被获取。它对我们有用。

          【讨论】:

          • 为什么要按值传递 std::string?应该通过 const 引用。即使在进行读写访问时,您也应该默认通过引用传递。
          • 如果你想在函数中修改一个原语怎么办?您如何满足第 1 点的情况?
          • +1,非常明智。 @aja pass by pointer (number 3) @ron number 2 这么说。 “应该”确实是一个偏好问题
          • @ronag:如果你传递字符串,你通常期望传递值语义。 std::string 对小字符串进行特殊处理以降低副本成本。尚未在优化此功能有帮助的情况下运行。
          • 我假设引用计数,但经过一些谷歌搜索,这似乎已经过时了。我会编辑。
          【解决方案6】:

          可能不是问题的答案。只是亲吻。

          int main()
          {
                  multimap<string, string> adjacencyMap;
                  adjacencyMap.insert(std::make_pair("s", "a"));
                  adjacencyMap.insert(std::make_pair("s", "v"));
                  adjacencyMap.insert(std::make_pair("s", "g"));
                  return 0;
          }
          

          【讨论】:

          • 谢谢!虽然这不能回答我的问题,但我不知道多图。而且这种用法似乎非常适合这种情况。
          • 另一方面,请注意这种方法似乎存在内存问题。使用多重映射时,相同的键会重复存储多个。在我的方法中,由于密钥是唯一的,它们只存储一次并且空间使用更少。对此有什么想法吗?
          • 那是特定于实现的。我相信大多数实现在插入后只存储一个密钥。
          • 我不知道这一点,在迭代时给你一个对的引用,如果他们正在实施你正在谈论的优化,他们将很难返回。
          【解决方案7】:

          一个好的经验法则:“尽可能使用引用,必要时使用指针”。

          【讨论】:

            【解决方案8】:

            我真的不明白你为什么遇到这么多麻烦:

            std::map < std::string, std::vector<std::string> > adjacencyMap;
            std::vector<std::string>& sFriends = adjacencyMap["s"];
            sFriends.push_back("a");
            sFriends.push_back("v");
            sFriends.push_back("g");
            

            你为什么在这里插手shared_ptr?这种情况当然不需要!

            【讨论】:

              猜你喜欢
              • 2023-04-09
              • 1970-01-01
              • 2020-03-14
              • 2012-03-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-05-14
              • 2014-07-26
              相关资源
              最近更新 更多