【问题标题】:Move semantic and an object-type parameter移动语义和对象类型参数
【发布时间】:2015-12-17 12:11:14
【问题描述】:

我正在阅读this 关于移动语义的回答并提出了一个问题。他描述了所谓的 move and swap 成语:

unique_ptr& operator=(unique_ptr source)   // note the missing reference
{
    std::swap(ptr, source.ptr);
    return *this;
}

由于移动赋值运算符应该对 rvalue 引用进行操作,我认为将 rvalue 引用作为参数传递是可以接受的。这是一个例子:

#include <iostream>

struct A {
    A(){ }
    virtual ~A(){ }
    A(A&&){ }
};

void foo(A a){
    std::cout << "foo(A)" << std::endl;
}

int main()
{
    foo(*new A);
}

DEMO

但是编译器警告我它试图复制引用的对象并失败,因为复制构造函数被删除。我不明白为什么在unique_ptr 的示例中它是正确的。当我们调用该函数时,该对象应该是复制,所以没有意义move语义。

你不能解释一下吗?

【问题讨论】:

  • 我不确定您对 c++ 的掌握程度有多强,*new T 通常是不理解值语义的结果。你在现实生活中想要的是foo(A{});,但你当然可能知道,这只是学术性的。
  • *new A 是一个左值。它指定存储对象的内存位置。要移动你必须写std::move(*new A)(这会泄漏内存)
  • "*new A",你怎么去delete那个A

标签: c++ c++11 move-semantics


【解决方案1】:

表达式*(new A) 不是右值。

什么表达式是右值的一般规则(不是the actual rule,只是一个快速的)是这样的:它要么是临时的,要么是你明确称为std::move 的东西。而*(new A) 不是临时的。而且你没有打电话给move。所以它不是右值。

改用A() 试试。

【讨论】:

    【解决方案2】:

    调用移动构造函数从相同类型的右值构造一个新对象。如果您尝试将 lvalue 传递给按值采用仅移动类型的函数,则它需要 copy 构造函数,您将收到错误。

    void f(std::unique_ptr<Foo> p);
    std::unique_ptr<Foo> p;
    f(p);  // error
    f(std::move(p));  // OK
    

    在您的示例中,可以这样做:

    foo(std::move(*new A));
    

    *new A 单独不是一个可能的参数,因为取消引用指针总是会产生一个左值。

    【讨论】:

      猜你喜欢
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 2013-03-18
      • 2013-05-20
      相关资源
      最近更新 更多