【问题标题】:Why is using move semantics in this way invalid?为什么以这种方式使用移动语义无效?
【发布时间】:2013-05-25 15:13:49
【问题描述】:

当我遇到这个案例时,我正在追踪一个编译错误:

struct Y        
{               
  int&& y;      
  Y(int&& y)    
    : y(y)      
  {             
  }             
};              

struct ZZ {};   
struct Z        
{               
  ZZ&& z;       
  Z(ZZ&& z)     
    : z(z)      
  {             
  }             
};

这些都失败了:

exec.cpp: In constructor ‘Y::Y(int&&)’:
exec.cpp:57:10: error: invalid initialization of reference of type ‘int&&’ from expression of type ‘int’
exec.cpp: In constructor ‘Z::Z(ZZ&&)’:
exec.cpp:67:10: error: invalid initialization of reference of type ‘ZZ&&’ from expression of type ‘ZZ’

但我不确定为什么。这里有什么问题?

我正在使用带有 -std=gnu++0x 选项的 g++4.5.3,但它也与 -std=c++0x 选项一起使用。

【问题讨论】:

  • 我很难找到将右值引用存储为成员的情况。您能否详细说明问题的背景?
  • 实际上,我只是想了解一下移动语义以及 && 的真正含义。我不确定是否有原因。
  • 更新:我认为将 r 值引用作为成员几乎没有任何价值,并且可能非常危险,如果具有该成员的对象具有任何重要的生命周期。可能有一些价值,但看起来很小。

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


【解决方案1】:

任何有名字的东西都是左值。这意味着构造函数参数y 是一个左值(类型为右值引用int),因为它有一个名称“y”。

使用std::move(y) 将其转回r 值。

【讨论】:

  • 哦,我明白了。 int & i 表示 i 是对命名左值的引用,int && i 表示 i 是对命名右值的引用。那正确吗?但我认为,采用 int && i 之类的函数可能会采用 l 或 r 值。我将不得不做更多关于移动语义的阅读......
  • @Adrian int &i 表示i 是对int 类型的左值的引用。 int &&i 表示i 是对int 类型的r 值的引用。在这两种情况下,i itself 都是左值。不,右值引用 (&&) 不能绑定到左值。此外,没有“命名 r 值”这样的东西。当某物有名字时,它就是一个左值。
  • @Angew:int &int && 都是引用。这些类型之一的变量的 id 表达式始终是 int。区别在于引用可以绑定到什么样的值。
  • @Angew:对不起,我的意思不是命名的 r-value,而是通过 r-value 引用为 r-value 命名。但是如果你有一个右值引用,这意味着它现在是一个左值,因为它有一个名字?对吗?
  • @Adrian 所指的 r 值仍然是 r 值。它是您可以访问它的参考变量,它是一个左值。 std::move() 允许您将其称为 r 值,因为它是一个表达式,而不是一个名称。您可以将std::move(r) 视为返回“r 所指的右值”。
【解决方案2】:

你需要说: y(std::move(y))。这是获得可以绑定到右值引用的表达式的唯一方法。只是裸表达式 y 是一个左值。

(请注意,存储引用类成员非常危险且难以纠正。)

【讨论】:

  • 请注意,虽然std::move 肯定是正常 方式,但同样肯定不是唯一方式。 std::move 是用普通的 C++ 编写的,you can duplicate it yourself 是随意编写的(本质上,它只不过是一个简单的 static_cast)。
  • @JerryCoffin:是的,当然。 static_cast<T&&>(x) 的值,其中T 是一个非引用类型,是一个 xvalue,因此可以绑定到一个右值引用。我认为这个问题的答案是正确的:-)
  • 是的,我知道当让成员引用某物时,对象的生命周期必须小于被引用对象的生命周期,否则会产生相当于悬空指针的结果。
  • 事实上,作为成员引用 r 值比引用 l 值更危险,因为 r 值是临时的,无法保证其寿命。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-26
  • 2021-07-19
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多