【问题标题】:Will this pair be moved?这对会搬家吗?
【发布时间】:2013-07-09 17:05:12
【问题描述】:

在 C++11 标准下,是否保证将以下对移动到函数中?

//objects available: key, value
//corresponding type available: pairtype
//function available: void foo(pairtype pair); copies the pair by default

foo({std::move(key),std::move(value)}); //pair moved?

还是我必须自己动手?

foo(std::move(pairtype(std::move(key),std::move(value))); //needed?

【问题讨论】:

    标签: c++ c++11 move-semantics std-pair


    【解决方案1】:

    初始化器列表不是表达式,因此它们没有类型,也不会产生值。这意味着以下内容:

    {std::move(key),std::move(value)}
    

    本身创建一对。初始化器列表只是一个用于初始化的语法结构,在这种情况下,函数参数将通过直接std::move(key)std::move(value) 作为参数调用pairtype 的构造函数来构造。

    不涉及创建临时对象 - 唯一需要注意的是在执行列表初始化时不会考虑 explicit 构造函数(例如,这不适用于 std::tuple<> 的实例)。

    这意味着我们刚才讨论的foo的调用,即:

    foo({std::move(key),std::move(value)}
    

    在技术上与此调用不同:

    foo(std::move(pairtype(std::move(key),std::move(value)))
    

    在这里,您有意创建一个临时变量并将其移动到函数参数中(编译器可能会根据 12.8/31 忽略此移动,但这是另一回事)。

    注意,这里对std::move() 的调用是多余的,因为临时变量是右值。无论如何,函数参数将从临时对象移动构造。因此,您可以写:

    foo(pairtype(std::move(key),std::move(value)))
    

    注意,pairtype 将是 std::pair<> 类模板的一个实例,这意味着您必须手动指定模板参数。为避免这种情况,您可以使用std::make_pair():

    foo(std::make_pair(std::move(key),std::move(value)))
    

    【讨论】:

    • 我认为显式构造函数只是不考虑列表复制初始化,这将在 C++14 中修复
    • @TemplateRex:不确定 C++14,但在 C++11 中,将参数传递给函数是复制初始化上下文(参见 8.5/15 和 8.5.4/1)。因为这里我们是列表初始化,所以这是一个复制列表初始化(参见 8.5.4/1),适用的是 8.5.4/3(第 4 条)和 13.3.1.7/1。
    • 啊,是的,我读的太快了。那么这同样适用于emplace 之类的函数(采用右值引用)吗?他们也可以不调用显式构造函数吗?
    • @TemplateRex:如果我正确理解了这个问题,我认为他们可以。 emplace 函数只是直接调用构造函数并完美转发它们收到的参数,因此它不是复制初始化上下文,而是直接初始化上下文。
    猜你喜欢
    • 2013-08-28
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 1970-01-01
    相关资源
    最近更新 更多