zoukankan      html  css  js  c++  java
  • Effective C++ 笔记 —— Item 21: Don't try to return a reference when you must return an object.

    Consider a class for representing rational numbers, including a function for multiplying two rationals together:

    class Rational 
    {
    public:
        Rational(int numerator = 0, int denominator = 1);  // see Item 24 for why this constractor isn’t declared explicit
        // ...
    private:
        int n, d; // numerator and denominator
        friend const Rational operator*(const Rational& lhs, const Rational& rhs); // see Item 3 for why the return type is const
    };

    A function can create a new object in only two ways: on the stack or on the heap.

    const Rational& operator*(const Rational& lhs, const Rational& rhs) // warning! bad code!
    {
        Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
        return result;
    }

    because it has been destroyed. Any caller so much as glancing at this function’s return value would instantly enter the realm of undefined behavior.

    const Rational& operator*(const Rational& lhs, const Rational& rhs) // warning! more bad code!
    {
        Rational *result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
        return *result;
    }

    who will apply delete to the object conjured up by your use of new?

    Even if callers are conscientious and well intentioned, there’s not much they can do to prevent leaks in reasonable usage scenarios like this:

    Rational w, x, y, z;
    w = x * y * z; // same as operator*(operator*(x, y), z)

    Here, there are two calls to operator* in the same statement, hence two uses of new that need to be undone with uses of delete. Yet there is no reasonable way for clients of operator* to make those calls, because there’s no reasonable way for them to get at the pointers hidden behind the references being returned from the calls to operator*. This is a guaranteed resource leak.

    The right way to write a function that must return a new object is to have that function return a new object. For Rational’s operator*, that means either the following code or something essentially equivalent:

    inline const Rational operator*(const Rational& lhs, const Rational& rhs)
    {
      return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
    }

    Things to Remember:

    • Never return a pointer or reference to a local stack object, a reference to a heap-allocated object, or a pointer or reference to a local static object if there is a chance that more than one such object will be needed. (Item 4 provides an example of a design where returning a reference to a local static is reasonable, at least in single-threaded environments.)
  • 相关阅读:
    源代码搭建应用(一)——动手搭建自己的计算集群系统
    [转载]Ubuntu 14.04中root 密码忘记解决方法
    如何用路由器改成WiFi Pineapple系统镜像网络流量
    DELPHI黑客编程(一):正向后门原理实现
    OpenWrt 路由器过滤广告的N种方法
    Windows 10 上强制Visual Studio以管理员身份运行
    DB2修改表字段
    Git Fast-forward提交
    C#(去、过滤)掉字符中的换行符
    VS读取文件或写入文件时出现中文乱码问题
  • 原文地址:https://www.cnblogs.com/zoneofmine/p/15238915.html
Copyright © 2011-2022 走看看