And*_*iov 7 c++ temporary-objects c++11 c++14 c++17
我有一个现有的功能:
void foo(const Key* key = nullptr)
{
// uses the key
}
Run Code Online (Sandbox Code Playgroud)
我想将它指向临时Key对象(即rvalue),如:
foo(&Key());
Run Code Online (Sandbox Code Playgroud)
这会导致编译错误,但是在c ++ 11/14中有一种方法可以做到这一点吗?我当然可以这样做:
Key key;
foo(&key);
Run Code Online (Sandbox Code Playgroud)
但我不需要对象Key,我只需要它在foo()和foo()中
或者我可以这样做:
foo(new Key());
Run Code Online (Sandbox Code Playgroud)
但是这个对象不会被删除.
我不认为这是一个好主意,但如果你真的想要一个临时的而且无法改变foo,你可以将临时转换为const&:
int main()
{
foo(&static_cast<const Key&>(Key{}));
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以在方便的函数后面"隐藏"对象的创建:
template <typename T, typename F, typename... Ts>
void invoke_with_temporary(F&& f, Ts&&... xs)
{
T obj{std::forward<Ts>(xs)...};
f(&obj);
}
int main()
{
invoke_with_temporary<Key>(&foo);
}
Run Code Online (Sandbox Code Playgroud)
另一种选择:提供foo一个引用的重载:
void foo(Key&& key)
{
foo(&key);
}
Run Code Online (Sandbox Code Playgroud)
这是一个实用函数。std::move它基本上是1的倒数:
template<class T>
T& as_lvalue( T&& t ) { return t; }
Run Code Online (Sandbox Code Playgroud)
如果使用错误,可能会导致悬空引用。
然后你的代码就变成:
foo(&as_lvalue(Key()));
Run Code Online (Sandbox Code Playgroud)
“无法获取临时地址”的目标是因为否则您可能会由于隐式临时创建等原因而获得极其意外的行为。
在这种情况下,我们明确地获取临时地址。
它并不比创建命名值、调用函数,然后立即丢弃命名值更危险。
1 std::move接受一个 l 或 r 值并返回对其的右值引用,表明消费者应将其视为临时值,其存在将很快被丢弃。 as_lvalue接受 l 或 r 值引用并返回对其的左值引用,表明使用者应将其视为非临时对象,其存在将持续存在。
它们都是有效的操作,但std::move更重要。(std::move可以称为as_rvalue真的)。我建议不要使用像unmove.
只需自己控制丢弃变量的范围即可:
{
Key key;
foo(&key);
} // <-- 'key' is destroyed here
Run Code Online (Sandbox Code Playgroud)