【问题标题】:Const reference to extend object's life followed by const_cast, is it a good idea?const 引用来扩展对象的生命,然后是 const_cast,这是个好主意吗?
【发布时间】:2017-04-05 11:18:34
【问题描述】:

考虑以下返回大对象的函数:

std::list<SomethingBig> DoSomething()
{
    std::list<SomethingBig> TheList;
    //do stuff
    return TheList;
}

我想获取列表,而不是它的副本。因为如果我必须复制这样的对象,性能代价是昂贵的。我知道返回值优化可以为我解决这个问题,但依靠优化来优化坏代码并不是最好的方法(对吧?)。

避免复制和延长对象寿命的一种简洁方法是使用常量引用(请test it before calling it a dangling reference,因为它不是):

const std::list<SomethingBig>& theList = DoSomething();

在 C++11 中,可以使用std::move 来避免复制。但是,我正在开发一个 C++03 程序,我必须这样做:

const std::list<SomethingBig>& list1 = DoSomething();
const std::list<SomethingBig>& list2 = DoSomethingElse();

现在我需要splice 将列表放在一起。我这样做的唯一方法是复制所有内容,或者const_cast这些列表并拼接它们。有没有更好的解决方案?

【问题讨论】:

  • 不确定,但我认为这是个坏主意。而且您可以依赖 RVO,为什么不呢?
  • @AlexanderLapenkov 没有什么特别的原因,除了我会依赖可能存在或不存在的优化来优化一些写得不好的代码。如果没有其他选择,我可能会这样做。
  • 动态分配列表?
  • @Drax 这不是我的职责。
  • @TheQuantumPhysicist 好的,你拼接列表,那么你打算如何处理数据?您要么想将它复制到某个地方,要么只是遍历拼接列表。这两种操作都可以在没有将列表拼接到其中一个引用的情况下完成。

标签: c++ c++03 const-cast copy-elision return-value-optimization


【解决方案1】:

只需按值返回,由于 NRVO,它会比引用和std::move 更好,这不是“对坏代码的优化”,而是一种让好代码快速工作的方法。

据我所知,NRVO 确实不能保证会发生(与 RVO 不同,自 c++17 以来这将是必须的),但它不太可能编译器不会省略复制到这里。

无论如何,依靠复制省略比使用const_cast技巧安全得多,而且比移动便宜。

Both clang and gcc elide the copy with -std=c++03 -O0

【讨论】:

    【解决方案2】:

    DoSomething...()的接口改成std::list&lt;SomethingBig&gt; &amp; DoSomething(std::list&lt;SomethingBig&gt; &amp;)怎么样? 列表对象的生命周期将在DoSomething()DoSomethingElse() 之外进行控制。例如:

    std::list<SomethingBig> list;
    DoSomethingElse(DoSomething(list));
    

    【讨论】:

    • 就像我在 cmets 中提到的......这不是我的职责。
    猜你喜欢
    • 2016-04-10
    • 2011-08-14
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 2014-10-15
    相关资源
    最近更新 更多