内联void addTask(任务任务)vs内联void addTask(const任务和任务)

时间:2014-12-25 20:26:06

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

我曾经通过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 &需要创建一个副本,但我知道事情并不像看起来那么简单。这足以提及 RVO http://en.wikipedia.org/wiki/Return_value_optimization) - 我确信还有更多的事情需要考虑(我还没有意识到)。< / p>

我知道inline实际上只是编译器的建议,而不是订单。但是它会改变const & vs & vs by value之战中的任何内容吗?

我正在使用VC ++ 2013,我并没有过多关注gcc。

P.S。请注意,App::addTask致电Timeline::add致电vector::push_back。所以参数传递的时间超过一次 - 我应该同时制作相同“类型”的App::addTaskTimeline::addconst & vs & vs by value)。

1 个答案:

答案 0 :(得分:3)

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

当然,当通过值传递时,值恰好是左值,也就是说,为了让它移动而不是复制,在传递时你需要std::move()它(更多的副本可以&# 39;无论如何都要被遗弃):

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

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

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

此版本也不会被允许删除副本,但它可能有利于根据合适的转换在原位创建更昂贵的版本。

但是,我没有任何基准来确定差异。如果有人能够提出一个合适的方法来衡量差异,我很乐意在我的基准测试套件中添加相应的基准,并用结果来补充这个答案。