paulQuei / gitment

Comment System for qiangbo.space
0 stars 0 forks source link

C++中的值类别 #98

Open paulQuei opened 3 years ago

paulQuei commented 3 years ago

https://paul.pub/cpp-value-category/#id-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99%E4%B8%8E%E6%8E%A8%E8%8D%90%E8%AF%BB%E7%89%A9

C++中的值类别, C++, lvalue,rvalue,rvalue-ref,move,perfect-forward, 表达式是C++语言的基石。每个表达式都有两个属性:类型(type)和值类别(value category)。前者是大家都熟悉的,但是后者却可能是我们不太在意的。本文的目的是介绍与值类别相关的一些知识。

wangzhankun commented 3 years ago

你好,关于这句话:glvalue可以自动转换成prvalue。例如:int a = b,等号右边的lvalue会自动转换成rvalue。我没太理解。为什么等号右边的是lvalue,等号左边的是rvalue呢?一句glvalue是拥有身份的表达式,它对应了一块内存地址。glvalue有lvalue和xvalue两种形式的说法,不应该等号左边的是lvalue吗?因为他有内存地址。

wangzhankun commented 3 years ago

我看懂glvalue可以自动转换成prvalue。例如:int a = b,等号右边的lvalue会自动转换成rvalue这句话了。希望您可以换个表述方法。我第一次产生误解是因为=的缘故。我以为你说的是等号右边是lvalue,等号左边是rvalue。而实际上您表达的意思应该是b本身是lvalue,但是将其放到等号右边需要赋值给a(a也是lvalue),那么b就会隐式地发生lvalue-to-rvalue的转变。lvalue-to-rvalue 转换实现了两件事:(1)如果某个场合需要一个 rvalue 表达式,那么 lvalue 也能用上去(比如,赋值运算符“=”的右侧,或是参与数学运算,比如 x+y )(2)它让编译器知道,应该去哪个位置读取一个变量的内存值。

wangzhankun commented 3 years ago

const类型的左值引用是可以绑定到右值上, const int& a = 1,那么请问内存空间是如何分配的呢?是在堆里面还是栈里面呢?const类型的左值引用绑定右值的过程中究竟发生了什么呢?

Aneureka commented 3 years ago

这个报错中的lvalue就是数字表达式3的值类别。

这里应该解释成「这里“3”所在的位置需要是左值,但“3”不是」吧,而不是「表达式“3”的值类别是lvalue」

Aneureka commented 3 years ago

int main()
{
  X h1(1000);                // regular constructor
  X h2(h1);                  // copy constructor (lvalue in input)
  X h3 = createX(2000);      // move constructor (rvalue in input) 

  h2 = h3;                   // assignment operator (lvalue in input)
  h2 = createX(500);         // move assignment operator (rvalue in input)
}

这段代码中的 X h3 = createX(2000) 应该是 X h3(createX(2000) 吗,表示移动构造函数?

shadw3002 commented 2 years ago

最后参数应用推导过程有点小问题,不过无伤大雅,emplace_back(1) 里面推导得到的应该是: void emplace_back(int&& e) { return func(forward<int&&>(int& e)); => return static_cast<int&&>(e); }

Aneureka commented 1 year ago
int main()
{
  X h1(1000);                // regular constructor
  X h2(h1);                  // copy constructor (lvalue in input)
  X h3 = createX(2000);      // move constructor (rvalue in input) 

  h2 = h3;                   // assignment operator (lvalue in input)
  h2 = createX(500);         // move assignment operator (rvalue in input)
}

这段代码中的 X h3 = createX(2000) 应该是 X h3(createX(2000) 吗,表示移动构造函数?

两年后过来看,发现我之前的评论是错的,当时还不清楚有多种初始化方式 😭