C++ 判断左值和右值 (使用代码判断)

C++的左值和右值的几率继承自C语言里。C++11以后引入右值。函数

左值和右值的根本区别就是左值可使用&取地址,而右值是不能够取地址的。还有一点就是,右值是能够赋值给左值,可是反过来就不行,即左值不能赋值给右值。通俗的讲,就是左值在=左边,右值在右边。设计

其实咱们若是在判断左值和右值的时候,抓住上面的概念,在代码里是很是容易判断左值和右值的,可是假如让咱们使用代码去判断左值和右值咱们又该如何作呢?code

在最初的时候,个人想法是取地址的这种办法,可是若是取的是左值还ok,可是若是咱们取右值的话,就会直接报错。这样编译都没法经过。因此使用这种办法是不太合适的。对象

在C++里引入了另一个和右值相关的概念,就是右值引用。首先我先简单介绍一下右值引用。继承

右值引用通常指向的是临时对象,即即将被销毁的对象。string

做为一种追求执行效率的语言,C++在用临时对象或函数返回值给左值对象赋值时的深度拷贝(deep copy)一直受到诟病。考虑到临时对象的生命期仅在表达式中持续,若是把临时对象的内容直接移动(move)给被赋值的左值对象,效率改善将是显著的。这就是移动语义的来源。io

与传统的拷贝赋值运算符(copy assignment)成员函数、拷贝构造(copy ctor)成员函数对应,移动语义须要有移动赋值(move assignment)成员函数、移动构造(move ctor)成员函数的实现机制。能够经过函数重载来肯定是调用拷贝语义仍是移动语义的实现。编译

右值引用就是为了实现移动语义与完美转发所须要而设计出来的新的数据类型。移动语义是为了提升效率,避免临时构造对象。二完美转发主要是普遍应用于泛型函数。function

我使用代码去判断左值和右值其实也是利用了右值引用的这个优势来实现的。具体看下面代码class

#include <stdio.h>
#include <string>

void print(const std::string& name) {
    printf("rvalue detected:%s\n", name.c_str());
}

void print(std::string& name) {
    printf("lvalue detected:%s\n", name.c_str());
}

int main() {
    std::string name = "lvalue";
    print(name); //compiler can detect the right function for lvalue
    print("rvalue"); // likewise for rvalue
}

实际上是很是巧妙的