我怎么知道作为右值传递的对象是否会被移动?
How do I know if object passed as r-value will get moved?
我正在将 lambda 传递给接受它作为 r 值引用的函数。
如果我的 lambda 是在函数调用本身中定义的,我真的不在乎它以后会发生什么。
但是如果我的 lambda 是一个变量(比如我想多次使用它)我确实想知道它没有被移动。
有没有办法知道它是否会被移动,从而在调用返回后相应地使其不可用或可用?
编辑:
澄清一下,lambda 不捕获任何内容。我关心的是函子本身:auto fn = [](int a){ return a; };
让我更难。我将函子作为右值传递:std::move(fn)
std::move 只是一个转换。它不会移动任何东西,但被调用者中的右值参数现在绑定到正确的右值。
问题是,fn
能保证感动吗?能保证不搬家吗?有任何保证吗?我可以让它以这种或那种方式表现还是由被调用者决定?
我想知道,因为我想知道我可以将 fn
作为函数参数传递两次吗?
编辑#2:
我们再来看一个案例。我必须调用一个带有容器的函数。矢量、地图或其他任何内容。函数签名表示 &&
。
我可以用 std move 或 std forward 包装我的容器,以将右值引用放入被调用方。这真的是一回事,因为他们都是美化演员。
现在,假设我使用了 std forward,因为我真的希望我的容器不会去任何地方。
我可以很容易地看到被调用者没有意识到我的意图,并在调用后移动我的容器使其无效(内脏)。
这是语言缺陷还是我遗漏了什么?
好吧,如果函数接受通用引用并且你想禁止移动,有很多选项供你选择,其中包括:
- 通过常量引用传递(C++17 有
std::as_const()
来简化它)。
- 将其保存为本地文件,不要转换为右值引用。看来你这样做了。
- 使用一些东西将右值引用显式转换为左值引用。
当然,除非 lambda 按值捕获具有不同于复制语义的移动语义的局部变量,并且被调用的函数实际上利用了这一点,否则这一点没有实际意义。
它真的会抓住机会吗?
检查合同,然后简单地信任它或尝试验证其实现。没有捷径。
更不用说 C++ 允许程序员明确选择退出它提供的(有限的)安全性。
我正在将 lambda 传递给接受它作为 r 值引用的函数。
如果我的 lambda 是在函数调用本身中定义的,我真的不在乎它以后会发生什么。
但是如果我的 lambda 是一个变量(比如我想多次使用它)我确实想知道它没有被移动。
有没有办法知道它是否会被移动,从而在调用返回后相应地使其不可用或可用?
编辑:
澄清一下,lambda 不捕获任何内容。我关心的是函子本身:auto fn = [](int a){ return a; };
让我更难。我将函子作为右值传递:std::move(fn)
std::move 只是一个转换。它不会移动任何东西,但被调用者中的右值参数现在绑定到正确的右值。
问题是,fn
能保证感动吗?能保证不搬家吗?有任何保证吗?我可以让它以这种或那种方式表现还是由被调用者决定?
我想知道,因为我想知道我可以将 fn
作为函数参数传递两次吗?
编辑#2:
我们再来看一个案例。我必须调用一个带有容器的函数。矢量、地图或其他任何内容。函数签名表示 &&
。
我可以用 std move 或 std forward 包装我的容器,以将右值引用放入被调用方。这真的是一回事,因为他们都是美化演员。
现在,假设我使用了 std forward,因为我真的希望我的容器不会去任何地方。
我可以很容易地看到被调用者没有意识到我的意图,并在调用后移动我的容器使其无效(内脏)。 这是语言缺陷还是我遗漏了什么?
好吧,如果函数接受通用引用并且你想禁止移动,有很多选项供你选择,其中包括:
- 通过常量引用传递(C++17 有
std::as_const()
来简化它)。 - 将其保存为本地文件,不要转换为右值引用。看来你这样做了。
- 使用一些东西将右值引用显式转换为左值引用。
当然,除非 lambda 按值捕获具有不同于复制语义的移动语义的局部变量,并且被调用的函数实际上利用了这一点,否则这一点没有实际意义。
它真的会抓住机会吗?
检查合同,然后简单地信任它或尝试验证其实现。没有捷径。
更不用说 C++ 允许程序员明确选择退出它提供的(有限的)安全性。