用std :: function移动语义

问题描述 投票:15回答:4

std::function提供了右值引用的构造函数。标准情况下,移动的功能对象会发生什么?它会是空的,以便再次调用没有效果吗?

c++ c++11 standards
4个回答
16
投票

在20.8.11.2.1p6下,function(function &&f)使f处于有效状态且具有未指定的值

空状态是有效状态,因此您应该期望移出的函数对象可以为空。

因为function执行类型擦除,并且功能对象可能会非常昂贵,所以将移出的对象留空的优化很有意义:

std::function<void()> g{std::bind{f, std::array<int, 1000>{}}};
std::function<void()> h{std::move{g}};

[通过从h的移动构造g之后,人们期望包含的bind已从g转移到h而不是复制,因此g将留空。

对于以下程序,gcc 4.5.1打印empty

#include <functional>
#include <iostream>
void f() {}
int main() {
    std::function<void()> g{f}, h{std::move(g)};
    std::cout << (g ? "not empty\n" : "empty\n");
}

这不一定是最理想的行为;内联小的可调用对象(例如函数指针)会导致以下情况:复制可调用对象比移动可调用对象和清空移出的对象要有效,因此另一种实现方式可能会使g处于非空可调用状态。


20
投票

关于这个问题有太多的困惑。我将尝试清楚地布置事物...

本节描述标准定义对象的移出状态:

17.6.5.15 [lib.types.movedfrom]

C ++标准库中定义的类型的对象可以从(12.8)。移动操作可以显式指定或隐式指定产生。除非另有说明,否则这些移出的物体应置于有效但未指定的状态。

这是什么意思?这意味着,给定一个std定义的移出对象,您可以对该对象执行任何操作,而无需先验了解该对象的状态。不需要先验状态的动作是没有先决条件的动作。

例如,您可以在从clear()移出的电话上调用vector,因为vector::clear()没有先决条件。但是您不能调用pop_back(),因为它确实有前提条件。

专门查看function的呼叫运营商:

20.8.11.2.4 [func.wrap.func.inv]

R operator()(ArgTypes... args) const

效果:INVOKE(f,std :: forward(args)...,R)(20.8.2),其中f是* this的目标对象(20.8.1)。

返回:如果R为空,则为空,否则为INVOKE的返回值(f,std :: forward(args)...,R)。

抛出:bad_function_call,如果!* this;否则,抛出任何异常通过包装的可调用对象。

请注意,没有前提条件或Requires子句。这意味着调用从function移出的function的调用运算符不是未定义的行为。无论function处于什么状态,此调用都不会违反任何先决条件。

请注意,在任何情况下,规范都不会说该调用无效。因此,无效是不可能的。

该调用将调用包装的函数,或抛出bad_function_call。这些是仅有的两个选择。它具有哪种行为取决于function对象的状态。并且function对象的状态未指定([lib.types.movedfrom])。


7
投票

标准情况下,移动的函数对象会发生什么?

它将处于有效状态(因此可以使用该对象),但是未指定其实际状态。最后一部分意味着调用任何要求对象处于specific状态的函数不一定有效。

它将为空,以便再次调用它没有效果吗?

无法假设会的。调用该函数要求它实际上具有要调用的函数。这是其状态的一部分。并且由于状态未指定,因此调用状态的结果也未指定。

如果要再次以某种有意义的方式使用该对象,只需创建一个新的function并将其分配给它:

function<...> old;
function<...> new_ = std::move(old);
old = function<...>(...); //Reset to known state.
old(...); //Call is well-defined.

0
投票

[func.wrap.func.con]:

function(function&& f);
template <class A> function(allocator_arg_t, const A& a, function&& f);

效果:如果!f,*这没有目标;否则,将f的目标构造为* this的目标,使f处于有效状态且未指定值。

© www.soinside.com 2019 - 2024. All rights reserved.