代码之家  ›  专栏  ›  技术社区  ›  Narek

C++引用类型推荐用法

  •  11
  • Narek  · 技术社区  · 16 年前

    我在C++编程超过5年,而且从来没有遇到过任何引用变量的地方,除了函数参数(如果你不想复制你作为函数参数传递的内容)。因此,有人会指出C++引用变量引用的情况(我的意思是它提供了任何好处)来使用。

    13 回复  |  直到 11 年前
        1
  •  16
  •   Community CDub    8 年前

    作为不透明集合访问器/变异器的返回值

    这个 operator[] 属于 std::map 返回引用。


    缩短引用变量所需的文本

    如果你怀念过去的学校 with Foo do ... 语句(这是Pascal语法),您可以编写

     MyString &name = a->very->long_->accessor->to->member;
     if (name.upcase() == "JOHN") {
        name += " Smith";
     }
    

    另一个例子可以在 Mike Dunlavey's answer


    声明某事只是一个参考

    引用在包装器对象和函子中也很有用——例如,在逻辑上不与成员接触但只与成员接触的中间对象中 参考文献 对他们来说。

    例子:

    class User_Filter{
      std::list<User> const& stop_list;
      public: Functor (std::list<User> const& lst)
        : stop_list(lst) { }
      public: bool operator()(User const& u) const
        {  return stop_list.exists(u); }
    };
    
    find_if(x.begin(),x.end(),User_Filter(user_list));
    

    这里的想法是 编译错误 如果不在此类对象的构造函数中初始化引用。编译时检查越多,程序就越好。

        2
  •  11
  •   Mike Dunlavey    16 年前

    这是一个很方便的案例:

    MyClass myArray[N];
    
    for (int i = 0; i < N; i++){
        MyClass& a = myArray[i];
        // in code here, use a instead of myArray[i], i.e.
        a.Member = Value;
    }
    
        3
  •  8
  •   David Rodríguez - dribeas    16 年前

    无论你想在哪里使用引用,当你被迫使用时使用指针。

    引用和指针共享部分语义:它们是不存在的元素的别名。主要区别在于内存管理:引用清楚地表明您不负责资源。另一方面,对于指针,它永远不会真正清晰(除非您指的是智能指针):您是假定要删除指针还是将其从外部删除?

    在必须管理内存、希望允许可选语义或需要在以后更改引用的元素时,必须使用指针。

    在其他情况下,可以使用引用或指针,引用更清晰,应该是首选。

    现在,正如你指出的,它们实际上是不需要的:你总是可以使用指针来引用所有的引用(甚至参数传递),但是事实上,你可以使用一个工具来做任何事情,这并不意味着没有更好的工具适合这个工作。

        4
  •  5
  •   Alexander Torstling    16 年前

    对于外部控制的非可选构造参数,我倾向于使用引用成员而不是指针。

    编辑(添加示例):

    假设您有一个数据库和一个dao类,它将数据库作为依赖项:

    struct Database {};
    struct PersonDao {
        const Database &m_d;
        PersonDao(const Database &d): m_d(d) {}
    };
    

    此外,数据库的范围是从dao外部控制的:

    int main() {
        Database d;
        PersonDao pd(d);
    }   
    

    在本例中,使用引用类型是有意义的,因为您不希望dao::m_d为空,并且它的生存期是外部控制的(在本例中是从主函数)。

        5
  •  3
  •   Rüdiger Hanke shraddha hattimare    16 年前

    我在函数参数中使用引用不仅是为了避免复制,而且是为了避免处理指针 NULL 适当时使用指针。指针模型A“也许有一个值,但也许没有( 无效的 )“,引用是一个需要值的明确语句。

    …而且要说得非常清楚(&>注释)。我倾向于避免使用指向模型“可能有多个值”的指针——这里向量是一个更好的选择。指向多个值的指针通常在C风格的编程中结束,因为通常还必须分别传递元素的值。

        6
  •  3
  •   Community CDub    8 年前

    使用常量引用为值命名,例如:

    const Vec3 &ba=b-a;
    

    这将命名该值,但不一定为其创建变量。理论上,这给了编译器更多的回旋余地,并可能允许它避免一些复制构造函数调用。

    (相关的非重复堆栈溢出问题,位于 Const reference to temporary . Herb Sutter链接有更多关于此的信息。)

        7
  •  3
  •   ragnarius    16 年前

    复制构造函数的参数必须作为引用传递,否则复制构造函数将需要在无休止的递归(堆栈溢出)中调用自身。

        8
  •  1
  •   kenny    16 年前

    我倾向于同意,但可能const返回值。

        9
  •  1
  •   Doug T.    16 年前

    好吧,您有两种方法可以给其他值起别名(忽略共享的指针等):指针和引用。

    引用必须在构造时初始化,才能引用其他内容。因此语义上的引用永远不会是空的。实际上,底层数据可能会消失,给你带来比指针更难调试的问题。所以我不确定这里是否有真正的优势,除非你有纪律性,并且与它们在动态分配的项目中的使用方式相一致。如果你也使用指针,你会避免同样的问题。

    也许更重要的是,引用可以不用考虑指针所引起的所有问题。这可能是主要优势。语义上的引用 这件事。如果您作为调用者/被调用者保证底层内存不会消失,就不必将用户与指针一起出现的任何问题混淆(我需要释放它吗?这可能是空的吗?等,可以安全使用参考方便。

    这方面的一个例子可能是查找枚举对应字符串的函数,

    const std::string& ConvertToString( someEnum val)
    {
       static std::vector< std::string > lookupTable;
       if (lookupTable.empty())
       {
          // fill in lookup table
       }
       // ignoring the cast that would need to happen
       return lookupTable[val]
    }
    

    这里,调用者和被调用者之间的约定保证返回类型始终存在。您可以安全地返回引用,并避免指针所邀请的一些问题。

        10
  •  1
  •   Michael Krelin - hacker    16 年前

    引用使代码更漂亮。所以在需要引用美化代码时使用它们。

        11
  •  1
  •   Pieter    16 年前

    流运算符就是一个明显的例子

    std::ostream & operator<< (std::ostream &, MyClass const &...) {
      ....
    }
    
    mystream << myClassVariable;
    

    很明显,您不需要指针,因为检查空值会使使用运算符变得非常繁琐I.S.O.很方便

        12
  •  0
  •   Satbir    16 年前

    我想申请一些案件:

    1) 在编写单例类时

     class singleton
        {
            singleton();
            explicit singleton(const singleton&);
            singleton& operator=(const singleton&);
        public:
            static singleton& instance()
            {
                static singleton inst;
                return inst;
            }
        };// this is called the 'Meyers' singleton pattern. refer to More Effective C++ by  Scott Meyers
    

    它有所有的好处,但是避免使用新的操作员

    **2)**这里没有空引用。引用必须始终引用某个对象。因此,如果您有一个变量,其目的是引用另一个对象,但可能没有对象引用,则应该将变量设为指针,因为这样您就可以将其设置为NULL。另一方面,如果变量必须总是引用一个对象,也就是说,如果您的设计不允许变量为空的可能性,那么您可能应该将变量作为引用

    **)**因为引用必须引用一个对象,C++要求引用被初始化:

      string& rs;             // error! References must
                              // be initialized
    
      string s("xyzzy");
    
      string& rs = s;         // okay, rs refers to s
    
    Pointers are subject to no such restriction
    

    没有空引用这样的事实意味着它可以比引用指针更有效地使用引用。那是因为在使用之前不需要测试引用的有效性

    **4)**指针和引用之间的另一个重要区别是指针可以被重新分配以引用不同的对象。然而,引用总是引用初始化它的对象:项m1,p10

      string s1("Nancy");
      string s2("Clancy");
    
      string& rs = s1;         // rs refers to s1
    
      string *ps = &s1;        // ps points to s1
    
      rs = s2;                 // rs still refers to s1,
                               // but s1's value is now
                               // "Clancy"
    
      ps = &s2;                // ps now points to s2;
                               // s1 is unchanged
    
        13
  •  0
  •   KitsuneYMG    16 年前

    我用了对ostream的引用而不是指针。我支持当类有很多运算符时,我更喜欢引用指针。