标签: rvalue

类,Rvalues和Rvalue引用

左值是绑定到存储器的确定区域的值,而右值是表达式值,其存在是临时的,并且不一定是指存储器的确定区域.只要在预期rvalue的位置使用左值,编译器就会执行左值到右值的转换,然后继续进行求值.

http://www.eetimes.com/discussion/programming-pointers/4023341/Lvalues-and-Rvalues

每当我们构造一个临时(匿名)类对象或从函数返回一个临时类对象时,虽然该对象是临时的,但它是可寻址的.但是,对象仍然是有效的右值.这意味着当编译器期望使用左值时,对象是a)可寻址的右值或b)从左值隐式转换为右值.

例如:

class A
{
public:
    int x;
    A(int a) { x = a; std::cout << "int conversion ctor\n"; }
    A(A&) { std::cout << "lvalue copy ctor\n"; }
    A(A&&) { std::cout << "rvalue copy ctor\n"; }
};
A ret_a(A a) 
{
    return a;
}

int main(void)
{
    &A(5); // A(5) is an addressable object
    A&& rvalue = A(5); // A(5) is also an rvalue
}
Run Code Online (Sandbox Code Playgroud)

我们还知道函数返回的临时对象(在下面的例子中a)是lvalues作为这个代码段:

int main(void)
{
    ret_a(A(5));
}
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

int conversion …

c++ reference rvalue lvalue rvalue-reference

13
推荐指数
1
解决办法
2080
查看次数

为什么不允许在一个ref-qualifier上超载?

显然,不允许在ref-qualifiers上重载 - 如果删除&或者&&(只是标记,而不是它们的函数),这段代码将无法编译:

#include <iostream>

struct S {
    void f() &  { std::cout << "Lvalue" << std::endl; }
    void f() && { std::cout << "Rvalue" << std::endl; }
};

int main()
{
    S s;
    s.f();   // prints "Lvalue"
    S().f(); // prints "Rvalue"
}
Run Code Online (Sandbox Code Playgroud)

换句话说,如果您有两个具有相同名称和类型的函数,则必须定义两者,如果您定义其中任何一个.我认为这是故意的,但是原因是什么?例如,为什么不允许调用&&rvalues 的版本(如果已定义),以及f()以下变体中的其他所有内容的"primary" (反之亦然 - 尽管这会让人感到困惑):

struct S {
    void f()    { std::cout << "Lvalue" << std::endl; }
    void f() && { std::cout << "Rvalue" …
Run Code Online (Sandbox Code Playgroud)

c++ overloading rvalue language-lawyer c++11

13
推荐指数
1
解决办法
589
查看次数

为什么std :: forward有两个重载?

鉴于以下参考折叠规则

  • T& & - > T&
  • T&& & - > T&
  • T& && - > T&
  • T&& && - > T&&

第三和第四条规则意味着T(ref qualifer) &&身份转变,即T&停留在T&T&&保持在T&&.为什么我们有两个重载std::forward?以下定义无法满足所有目的吗?

template <typename T, typename = std::enable_if_t<!std::is_const<T>::value>>
T&& forward(const typename std::remove_reference<T>::type& val) {
    return static_cast<T&&>(const_cast<T&&>(val));
}
Run Code Online (Sandbox Code Playgroud)

这里服务的唯一目的const std::remove_reference<T>&是不复制.并且enable_if有助于确保仅在非const值上调用该函数.我不完全确定是否const_cast需要它,因为它不是引用本身的const.

由于forward总是使用显式模板参数调用,因此我们需要考虑两种情况:

  1. forward<Type&>(val)这里Tin 的类型forward将是T&,因此返回类型将是身份转换T&
  2. forward<Type&&>(val)这里Tin 的类型forward将是T&& …

c++ reference rvalue perfect-forwarding c++11

13
推荐指数
1
解决办法
772
查看次数

为什么const为隐式转换?

在广泛阅读ISO/IEC 14882,编程语言 - C++后,我仍然不确定为什么const需要使用单个参数构造函数隐式转换为用户定义的类型,如下所示

#include <iostream>

class X {
public:
   X( int value ) {
      printf("constructor initialized with %i",value);
   }
}

void implicit_conversion_func( const X& value ) {
   //produces "constructor initialized with 99"
}

int main (int argc, char * const argv[]) {
   implicit_conversion_func(99);
}
Run Code Online (Sandbox Code Playgroud)



从第4节第3行开始

当且仅当声明T t = e时,表达式e可以隐式转换为类型T. 对于一些发明的临时变量t(8.5),其形式良好.某些语言结构要求将表达式转换为布尔值.在这样的上下文中出现的表达式e被称为在上下文中转换为bool并且当且仅当声明bool t(e)时才是格式良好的; 对于一些发明的临时变量t(8.5),其形式良好.隐式转换的效果与执行声明和初始化相同,然后使用临时变量作为转换的结果.如果T是左值引用类型(8.3.2),则结果是左值,否则为右值.当且仅当初始化将其用作左值时,表达式e用作左值.

接下来,我在8.5行6中找到了与用户定义类型相关的初始化器部分

如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的默认构造函数的类类型.

最后,我以12.3第2行结束了有关用户定义的转换的信息

用户定义的转换仅在明确无误的情况下应用(10.2,12.3.2).

不用说,10.2和12.3.2没有回答我的问题.

  1. 有人可以了解const隐含转换的影响吗?
  2. 是否使用const12.3第2行使转换"明确"?
  3. 是否会const以某种方式影响第4节中谈到的左值与右值?

c++ constructor const rvalue implicit-conversion

12
推荐指数
1
解决办法
3075
查看次数

Const引用和左值

我们不能写,int& ref = 40因为我们需要lvalue在右侧.但我们可以写const int& ref = 40.为什么这可能?rvalue而是40lvalue

我知道这是一个例外,但为什么呢?

c++ rvalue lvalue

12
推荐指数
2
解决办法
4156
查看次数

为什么std :: shuffle采用右值引用?

从C++ 11开始,std::shuffle()对随机位生成器进行右值引用:

template<class RandomIt, class URBG>
void shuffle(RandomIt first, RandomIt last, URBG&& g);
Run Code Online (Sandbox Code Playgroud)

所以我可以这么称呼它:

std::vector<int> v = {...};
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);
Run Code Online (Sandbox Code Playgroud)

这揭示了我对C++的理解错误,我今天早上通过阅读无法满足:在这里使用右值引用可以获得什么?换句话说,为什么不这样做

template<class RandomIt, class URBG>
void shuffle(RandomIt first, RandomIt last, URBG& g);
Run Code Online (Sandbox Code Playgroud)

c++ rvalue c++11

12
推荐指数
1
解决办法
808
查看次数

为什么这里的枚举变量是右值?

例子:

typedef enum Color
{
    RED,
    GREEN,
    BLUE
} Color;

void func(unsigned int& num)
{
    num++;
}

int main()
{
    Color clr = RED;
    func(clr);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译时出现以下错误:

<source>: In function 'int main()':

<source>:16:9: error: cannot bind non-const lvalue reference of type 'unsigned int&' to an rvalue of type 'unsigned int'

     func(clr);

         ^~~
Run Code Online (Sandbox Code Playgroud)

我认为clr我传递给的变量 ( )func(unsigned int&)是一个左值。我可以获得的地址clr并可以为其分配另一个值。当我尝试将它传递给 时,为什么它会变成右值func(unsigned int&)

c++ rvalue lvalue rvalue-reference c++11

12
推荐指数
1
解决办法
931
查看次数

C++ 右值参数

我写这个代码:

#include <iostream>
using namespace std;
class Foo
{

public:
    int a = 0;
    Foo()
    {
        cout << "ctor: " << this << endl;

    }
    ~Foo() {
       cout << "dtor: " << this << endl;
    }
};

Foo f()
{
    Foo foo;
    cout << "f " << &foo << endl;
    return foo;
}
void ff(Foo &&ffoo)
{
    cout << "ff " << &ffoo << endl;

}

int main()
{
    ff(f());
    std::cout << "Hello World!\n";
}
Run Code Online (Sandbox Code Playgroud)

输出看起来不错:

ctor: 0x7ffeda89bd7c
f 0x7ffeda89bd7c …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue

12
推荐指数
1
解决办法
216
查看次数

什么是"将移动语义扩展到*这个"?

请问,有人可以用简单的英语解释什么是"将移动语义扩展到*这个"?我指的是这个提议.所有我们正在寻找的是什么,为什么我们需要它.请注意,我确实理解rvalue引用通常是什么,构建了移动语义.我无法理解这样的扩展为rvalue引用添加了什么!

c++ this rvalue move-semantics c++11

11
推荐指数
2
解决办法
424
查看次数

为什么rvalues引用的变量不是rvalue?

假设我有一个函数的两个重载f.f(T&&)f(T&).然后在身体g: g(T&& t) { f(t);}过载f(T&)将调用因为t被认为是左值.

这对我来说非常令人惊讶.带签名的函数如何f(T&&)与类型的调用不匹配T&&?让我更加惊讶的是,一个电话f(static_cast<T&&>(t))实际上会调用rvalue超载f(T&&).

使这成为可能的C++规则是什么?是T&&不是类型吗?

c++ rvalue rvalue-reference

11
推荐指数
3
解决办法
1286
查看次数