gpt4 book ai didi

c++ - 错误地使用 move 的值

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:44:41 25 4
gpt4 key购买 nike

在转向 C++11 之后,我现在在我的构造函数中系统地按值传递我的字符串。但是现在,我意识到在构造函数的主体中使用值时更容易引入错误:

class A(std::string val):
_val(std::move(val))
{
std::cout << val << std::endl; // Bug!!!
}

我该怎么做才能减少出错的几率?

最佳答案

命名参数,其目的是以某种独特的方式被 move ,至少在构造函数的实现中是这样

A::A(std::string val_moved_from):
_val(std::move(val_moved_from))
{
std::cout << val_moved_from << std::endl; // Bug, but obvious
}

然后尽早离开它们(比如在构造列表中)。

如果你有这么长的构造列表,你可能会错过 val_moved_from 的两次使用在其中,这没有帮助。

另一种方法是编写解决此问题的提案。比方说,扩展 C++ 以便局部变量的类型或范围可以通过对它们的操作来更改,因此 std::safe_move(X)两者都从 X move 和标记 X作为一个过期的变量,在它的剩余范围内不再有效使用。当一个变量过期一半(在一个分支中过期,但在另一个分支中未过期)时,弄清楚该怎么做是一个有趣的问题。

因为这很疯狂,我们可以将其作为一个库问题来攻击。在一定程度上,我们可以在运行时伪造那些类型的技巧(类型改变的变量)。这很粗糙,但给出了想法:

template<typename T>
struct read_once : std::tr2::optional<T> {
template<typename U, typename=typename std::enable_if<std::is_convertible<U&&, T>::value>::type>
read_once( U&& u ):std::tr2::optional<T>(std::forward<U>(u)) {}
T move() && {
Assert( *this );
T retval = std::move(**this);
*this = std::tr2::none_t;
return retval;
}
// block operator*?
};

即,写一个只能通过move读取的线性类型, 在那之后阅读 Assert s 或抛出。

然后修改你的构造函数:

A::A( read_once<std::string> val ):
_val( val.move() )
{
std::cout << val << std::endl; // does not compile
std::cout << val.move() << std::endl; // compiles, but asserts or throws
}

使用转发构造函数,您可以公开一个没有read_once 的不那么荒谬的接口(interface)类型,然后将构造函数转发到带有 private 的“安全”(可能是 read_once<>)版本包装参数。

如果您的测试覆盖了所有代码路径,您会很高兴 Assert s 而不是空的 std::string s,即使你去move不止一次来自你的read_once变量。

关于c++ - 错误地使用 move 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17449157/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com