【问题标题】:inline void addTask(Task task) vs inline void addTask(const Task &task) [duplicate]内联无效添加任务(任务任务)与内联无效添加任务(常量任务和任务)[重复]
【发布时间】:2015-02-23 09:00:19
【问题描述】:

我曾经通过const & 或至少通过& 传递每个复杂结构。但是有了新的std::move 语义和编译器今天提供的所有优化,它仍然是选择吗?

考虑这样的例子:

struct Task{
    unsigned timeMS;
    void(*function)(unsigned, unsigned) = 0;
    Task(unsigned timeMS, void(*function)(unsigned, unsigned)) 
        : timeMS(timeMS), function(function){}
};

class Timeline{
    std::vector<Task> tasks;
    ...
};

class App{
...
public:
    inline void addTask1(const Task &task){ timeline.add(Task); }
    inline void addTask2(Task &task){ timeline.add(Task); }
    inline void addTask3(Task task){ timeline.add(Task); }
};

addTask1, addTask2, addTask3 中的哪一个是要走的路?假设App::addTask() 是一种被大量使用的方法。

我猜const &amp; 需要创建一个副本,但我了解到事情并不像看起来那么简单。提及 RVO (http://en.wikipedia.org/wiki/Return_value_optimization) 就足够了 - 我确信还有更多的事情需要考虑(我还不知道)。

我知道inline 实际上只是对编译器的建议,而不是命令。但它会改变const &amp; vs &amp; vs by value 的战斗吗?

我正在使用 VC++ 2013,我不太关注 gcc。

附:请注意,App::addTask 调用 Timeline::add,后者调用 vector::push_back。所以参数传递不止一次 - 我是否应该将App::addTaskTimeline::add 设为相同的“类型”(const &amp; vs &amp; vs by value)。

【问题讨论】:

  • Move 根本没有帮助,如果 const&amp; 或值在内联后编译成不同的东西,我会感到惊讶。
  • 在类定义中定义的成员函数是隐式内联的
  • @Pradhan 这个问题正是关于std::string,而不是关于用户定义的自定义结构。我不相信这是 1:1 的情况(例如,我猜 std::string 的复制构造函数成本是不同的)。
  • @PolGraphic 正如答案所解释的,如果您要复制参数,请按值传递。如果没有,请通过const &amp;。此外,如果您只是将其转发到其他地方,您可能需要研究完美的转发习惯。

标签: c++ c++11 pass-by-reference move-semantics


【解决方案1】:

按值传递还是const&amp; 是否合适取决于,显然接下来对对象做了什么。特别是当需要某种形式的对象副本并且传递的对象可能源自临时对象时,使用按值传递可能更可取:当按值传递时,允许编译器省略副本。当通过const&amp; 时,不允许复制省略(对于要省略的副本,编译器需要证明创建副本没有可观察到的副作用)。

当然,当按值传递时,该值恰好是一个左值,也就是说,要移动它而不是复制它,你需要在传递时std::move()它(进一步的副本无论如何都不能省略):

void addTask3(Task task) { timeline.add(std::move(task)); }

顺便说一句,你省略了完美转发版本:

template <typename T>
void addTask4(T&& task) { timeline.add(std::forward<T>(task)); }

此版本也不允许省略副本,但它可能具有优势,可以根据适当的转换在原位创建更昂贵的版本。

不过,我没有任何基准来确定差异。如果有人可以建议一种体面的方法来对差异进行基准测试,我很乐意在我的基准测试套件中添加一个相应的基准,并用结果来扩充这个答案。

【讨论】:

    猜你喜欢
    • 2018-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多