💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
C++中有个很重要的事情,就是对于类重载赋值运算符,而达到我们想要的结果。 先看看这几行代码: ~~~ //Window 是一个类 Window w; w = w; // 再傻的人也不会这么干 w[i] = w[j]; // 这个情况偶尔会发生 ~~~ 作为一个优秀的工程师,就要考虑到任何可能的情况。 看一段更加完整的代码: ~~~ class ScrollBar {}; class Window { ScrollBar *sb; public: Window(ScrollBar *s) : sb(s) {} Window() = default; Window& operator=(const Window&); }; Window& Window::operator=(const Window& rhs) { delete sb; sb = new ScrollBar(*rhs.sb); return *this; } int main() { Window w(new ScrollBar); Window w2(w); } ~~~ **这段代码到底有什么坑儿呢?** 设想一下,如果 *this 和rhs 是同一个实例对象呢? 那么 ~~~ delete sb; sb = new ScrollBar(*rhs.sb); ~~~ 就会造成严重的问题。 再delete sb后, 我们试图去访问一个已经被删除的rhs。这当然是致命的坑儿了。 跨越这个坑儿: ~~~ if (this == &rhs) return *this; delete sb; sb = new ScrollBar(*rhs.sb); return *this; ~~~ 上面这段代码几乎所有的教科书都会这么讲,但是曾经一个arcserver的工程师跟我讲,这样同样存在危险,不是完美的: 试想一下,如果我们delete sb后发生了异常怎么办?这个时候,就会有存在一个没有指向任何东西的指针。所以下面这样写会更好: ~~~ Window& Window::operator=(const Window& rhs) { if (this == &rhs) return *this; ScrollBar *sbOld = sb; sb = new ScrollBar(*rhs.sb); delete sbOld; return *this; } ~~~