C ++禁止转换为右值引用

时间:2015-05-11 21:03:30

标签: c++ c++11 move

与往常使用std::move'd的变量一样,之后使用它们是不安全的。

由于我编写了一个代码,我鼓励用户在不同的场合应用std::move,我想避免以错误的方式使用它,至少在几个关键的地方(所以有选择地说) “防止马基雅维利”。

因此,std::move的以下重载是一种有效的方法吗?或者你不鼓励使用它?

struct A
{
     void do_something() const { /* ... whatever ... */ }
};

namespace std
{
    auto move(A& t) noexcept = delete;
    auto move(A const& t) noexcept = delete;
    //possibly the same for volatile qualifier

    //possibly also specialize static_cast<A const&>, static_cast<A&>, etc.
}

// possibly set up another function "my_private_move"
// which I can use exclusively where it is appropriate.

int main()
{
    A a;
    // auto a_moved = std::move(a);      //disallow move of lvalue ref
    a.do_something();                    //otherwise this could be problematic

    A(A{});                             //direct initialization via move constructor is ok
    auto x2 = A{};                      
}

3 个答案:

答案 0 :(得分:7)

根据[namespace.std]:

,您的代码显示未定义的行为
  

如果将声明或定义添加到命名空间std 或将其添加到   命名空间std中的命名空间,除非另有说明。程序可以添加模板专业化   仅当声明取决于用户定义的类型时,才能将任何标准库模板添加到命名空间std   并且专业化符合原始模板的标准库要求,并未明确说明   禁止的。

您的用例不属于&#34;否则指定&#34;雨伞。除了未定义之外,还有一些值得怀疑的问题......你不允许这样做:

A a; 
f(std::move(a)); 
// just don't use a here

尽管可能比f(a)提高了性能。但是用户仍然可以明确地编写演员来完成相同的结果:

f(static_cast<A&&>(a)); // slightly more verbose move

答案 1 :(得分:3)

  

与使用std :: move'd的变量一样,它是不安全的   之后使用它们

这根本不是真的。使用已经移动的东西是完全安全的。在被标准移动后,有很多地方需要使用,例如std::swap,甚至只是破坏当地人。

无法做的事情是假设他们有任何特定的有效状态。但是他们必须具有某些有效状态。如果您正在创作A并且它不遵守这些规则,那么A就会被破坏并且应该被修复,而不是针对该问题进行帮助。

答案 2 :(得分:0)

  

A a;
  auto a_moved = std :: move(a); //禁止移动左值参考号   a.do_something(); //否则这可能会有问题

std :: move()的要点是取一个左值并返回一个右值,这样就可以调用你的移动构造函数或移动赋值。因此,要么删除移动构造函数并移动分配,要么用户只需要知道他们在做什么。以下是有关std :: move()http://en.cppreference.com/w/cpp/utility/move

的一些信息