C++进阶 —— 右值引用(C++11新特性)

【C++】右值引用(极详细版) 右值引用的两个价值;万能引用和完美转发 阅读详情

目录

一,左值与右值

左值 loactor value

右值 read value

二,右值引用

以值的形式返回对象的缺陷

三,移动语义

move函数

四,完美转发

forward函数


一,左值与右值

        左值与右值是C语言中的概念,但并没有严格的区分方式;在C++中每个表达式都有两个独立属性:类型和值分类;值类别决定表达式如何被使用,最主要的值类别为左值和右值;

        左右值根本的区别在于是否可通过取地址以获取对应内存地址;通俗来说,可以放在=左边的、或能取地址的称为左值,只能放在=右边的、或不能取地址的称为右值,但不完全正确;可看出,左值一定可以作为右值使用,右值一定不能为左值使用;

         expression
          /      \
     glvalue    rvalue
      泛左值      右值
       /  \      /  \
   lvalue  xvalue   prvalue
    左值    将亡值    纯右值

左值 loactor value

有标识符(变量名),占据特定内存位置且可取地址,可出现在赋值运算符左边;

  • 普通类型的变量可取地址,都认为是左值;
  • 如单个变量是引用或表达式运行结果是引用,则认为是左值;
  • const修饰的常变量是不可修改的只读类型,但可取地址,C++11认为是左值(常量左值);
  • 字符串字面量为左值,有固定内存位置可取地址,类型为const char[N](常量左值);
  • 右值引用本身是左值,所有有名字的引用变量本身都是左值;
int a = 1; //普通类型变量a为左值,可取地址&a
int arr[10]; arr[0]=1;
string s="hello"; s[0]='H'; //operator[]返回左值引用,所以vec[0]是左值

int& c = a; //引用变量c为左值
int& fun(int& a) { return a; }
fun(a) = 10; //表达式fun(a)运行结果是引用为左值

const int b = 1; //常变量b认为是常量左值
const char* good_ptr = "Hello"; //"Hello"是常量左值,可取地址(&"Hello")

//std::move(str)返回参数右值引用,这个返回的表达式本身是将亡值
void process(string&& str) {
    // 在函数内部,str是有名字的变量,所以是左值!
    string local = std::move(str); // 需要std::move将左值转为右值
}

右值 read value

临时的,没有名字,即将销毁的值;

  • 纯右值 Pure Right Value,无标识,通常用于初始化对象或计算表达式,生命周期仅限于当前表达式,绑定到右值引用会延长纯右值的生命周期,如:
    • 字面量(除了字符串字面量),100;
    • 算数表达式的结果,a+b;
    • 函数返回非引用类型,int add(int x, int y) { return x + y; };
    • lambda表达式,[](){ return 42; };
    • this指针;
100; 
int a,b;
int c = a + b; //隐式转换为右值
int add(int x, int y) { return x + y; } //函数返回的是值
string getName() { return "Alice"; } //函数返回临时对象
[](){ return 42; } 
this; //在成员函数中,this是纯右值
  • 将亡值 Expiring Value,是有身份(有明确内存地址)但即将结束生命周期(资源可被窃取);
    • 函数返回的局部对象;
    • 通常由 std::move 或 static_cast<T&&> 产生;
      • 返回类型为右值引用的函数调用表达式是 xvalue(将亡值),如std::move;
      • 转换为右值引用的类型转换表达式是 xvalue(将亡值),如static_cast<T&&>;
//函数返回的局部对象
string createString() {
    string local = "Hello";
    return local;  // 返回时,local变成将亡值
}

string str = "Hello";
string new_str = std::move(str);
string&& rref = static_cast<string&&>(str);

注:三个隐式自动转换

  • 左值转换为右值,如i+3;
  • 数组名为常量左值,在表达式中会转换为首元素地址;
  • 函数名为常量左值,在表达式中转换为函数地址;

二,右值引用

        C++98提出了引用的概念,引用即别名,引用变量与其引用的实体公共同一块空间,且引用的底层是通过指针来实现的,使用引用可提高程序的可读性;通常说的引用指的是左值引用(T&);

void swap(int& left, int& right)
{
	int tmp = left;
	left = right;
	right = tmp;
}

        为了提高程序的运行效率,C++11引入了右值引用(T&&),右值引用也是别名,但其只能对右值引用;

  • 右值引用也必须立即进行初始化操作;
  • 且只能使用右值进行初始化;
  • 可延长生命周期并修改;
    • 直接绑定到临时值;
    • 直接绑定到函数值返回;
    • 不能绑定到函数int&&返回;
int&& a = 1; //对右值进行引用
a = 10; //还可对右值引用进行修改
const int&& b = 1; //常量右值引用,无实际用处
//把返回值x存储在临时空间,int tmp = x;
int fun1(int x) { return x; } 
//把指向返回值x的地址存储在临时空间,会释放悬空,int& tmp = x;
int& fun2(int x) { return x; } 
//把指向返回值x+1的地址存储在临时空间,会释放悬空,int&& tmp = x+1;
int&& fun3(int x) { return x + 1; } 

int main() {
	int a1 = fun1(10); //将临时空间值存入a1
    //int&& a1 = fun1(10); //ok,可延长生命周期
	int a2 = fun2(10); //读取临时空间指向的值存入a2
	int a3 = fun3(10); //读取临时空间指向的值存入a3
    //int&& a3 = fun3(10); //不ok,不可延长生命周期	
}

引用与右值引用比较

  • T& 只能绑定左值,给对象起别名,作为函数参数可修改传入对象;
  • const T& 即可绑定左值也可绑定右值,只读访问;
  • T&& 只能绑定右值,实现移动语义和完美转发;

//普通类型只能引用左值,不能引用右值
int a = 10;
int& ra = a;
//int& rb = 10; 编译失败,10是右值

//常量左值引用,即可引用左值也可引用右值
const int& rc = a;
const int& rb = 10;
//右值引用只能引用右值,一般不能引用左值
int&& rd = 10;
//int&& re = a; 编译失败,a是左值
//int&& re = rd; 编译失败,rd是左值
//以下函数均可传入右值,int&& value会更优先因为更精确
void process(const int& value)
void process(int&& value) 

以值的形式返回对象的缺陷

        如一个类中涉及到资源管理,需显式提供拷贝构造、赋值运算符重载以及析构函数,否则拷贝对象或对象之间赋值就会出错(浅拷贝);

class String
{
public:
	String(const char* str = "")
	{
		if (nullptr == str)
			str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	String(const String& s)
		:_str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}

	String& operator=(const String& s)
	{
		if (this != &s)
		{
			char* tmp = new char[strlen(s._str) + 1];
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
		}
		return *this;
	}

	String operator+(const String& s)
	{
		char* tmp = new char[strlen(_str) + strlen(s._str) + 1];
		strcpy(tmp, _str);
		strcpy(tmp + strlen(_str), s._str);
		String strRet(tmp);
		return strRet;
	}

	~String() { delete[] _str; }
private:
	char* _str;
};

int main()
{
	String s1("hello");
	String s2("world");
	String s3(s1 + s2);
	return 0;
}

上述代码s1+s2调用operator+中,返回的是strRet值(将完值),s3创建过程为:

  • 创建一个临时对象接收然后strRet值,调用拷贝构造,String Tmp = strRet;
    • strRet出作用域将销毁;
  • 然后使用临时对象来构造s3,调用拷贝构造,String s3(Tmp);
    • 最后在销毁此临时对象Tmp;

        在这个过程中,strRet、Tmp,s3,都有自己独立的空间,相当于创建了三个内容完全相同的对象,浪费空间,程序效率低下,且临时对象作用不大;

右值引用和右值的区别

右值引用是类型,右值是值类别;

// a是一个左值,其类型是“对int的右值引用”
// 可理解为将一个字面量纯右值1生命周期延长,并给延长的对象起名为a
int&& a = 1;        

// 告知编译器将a作为右值处理,表达式结果为将完值
// 实际即为std::move函数的实现,等价于std::move(a)
// 核心意义是:启用移动语义
static_cast<int&&>(a); // 将一个左值a强制转换为右值

三,移动语义

         C++11新增的特性,以提高对象传递和拷贝时的效率;即通过将资源所有权从一个对象转移到另一个对象,来避免不必要的内存分配和数据复制;具体表现为,通过“右值引用”将移动构造或移动赋值运算符设置为优先于常规的拷贝构造或拷贝赋值运算符;

  • 即将一个对象中资源移动到另一个对象中的方式;
  • C++11中如需实现移动语义,必须使用右值引用;
class A
{
public:
	A(int a) :_a(a) { cout << "A(int a)._a=" << _a << endl; } //构造,注意A(int&& a)
	A(A& a) :_a(a._a) { cout << "A(A& a)._a=" << _a << endl; } //拷贝构造
	A& operator=(const A& a) { _a = a._a; return *this; } //赋值重载

	A(A&& a)noexcept :_a(a._a) { cout << "A(A&& a)._a=" << _a << endl; } //移动构造
	A& operator=(A&& a)noexcept { _a = a._a; return *this; } //移动赋值重载
private:
	int _a;
};

int main()
{
	A a1(1), a2(2); //调用 A(int a)
	A a3(a1); //调用 A(A& a)
	a3 = a2; //调用 A& operator=(const A& a)

	A a4(move(a1)); //调用 A(A&& a)
	a4 = move(a2); //调用 A& operator=(A&& a)
	return 0;
}

上述代码s1+s2调用operator+中,引入移动构造,将strRet中资源转移到临时对象中;

String(String&& s)
	:_str(s._str)
{
	s._str = nullptr;
}

引入移动构造后,s3创建过程为:

  • 创建一个临时对象接收然后strRet值,调用移动构造,String Tmp = strRet;
    • 将strRet中资源转移到临时对象中,strRet出作用域将销毁;
  • 然后使用临时对象来构造s3,调用移动构造,String s3(Tmp);
    • 将临时对象中资源转移到s3中,最后在销毁此临时对象Tmp;

整个过程只需创建一块堆内存即可,节省空间也提供运行效率;

    注:

    • 移动构造函数的参数,不要设置成const类型的右值引用,因为资源无法转移而导致移动语义失效;
    • 在C++11中如都没有显式创建拷贝构造、拷贝赋值、移动构造、移动赋值、析构函数,编译器会为类默认生成,但为浅拷贝,因此当类中涉及到资源管理时需显式定义移动构造;

    move函数

            按照语法右值引用只能引用右值,但有些场景可能需要用右值去引用左值实现移动语义;当需要用右值引用引用左值时,可通过move函数将左值转化为右值;移动语义接管资源后,被移动的对象(源对象)必须处于一个有效但未指定的状态;

    • 内置类型没有资源需要转移,移动=拷贝;
    • 自定义类型有资源要转移,需显式实现移动语义,标准库类型已实现;

    • 辅助函数,其唯一的功能就是将一个左值强制转化为右值引用,以实现移动语义;
    • 标准库的许多组件实现了移动语义,允许在参数为右值时直接转移对象的资产和属性的所有权,而无需复制,如string,vector等;
    • 注意,在标准库中,被移出的对象处于有效但未指定的状态;在操作后,被移出的对象应被销毁或分配一个新值;否则访问会产生一个未指定的值;
    • 被转化的左值,其生命周期并没有随左值的转化而改变,即std::move转化的左值变量不会被销毁;
    • STL中也有另一个move函数,将一个范围的元素搬移到另一个位置;
    //返回值
    static_cast<remove_reference<decltype(arg)>::type&&>(arg)
    template<class _Ty>
    inline typename remove_reference<_ty>::type&& move(_Ty&& _Arg) _NOEXCEPT
    {
        return ((typename remove_reference<_Ty>::type&&)_Arg);
    }
    int main()
    {
    	int a = 1;
    	int aa = move(a); 
    
    	string s = "abcd";
    	string ss = move(s); //实现移动语义,资源已转移,s已为空;
    
    	vector<int> v = { 1,2,3,4 };
    	vector<int> vv = move(v); //实现移动语义,资源已转移,v已为空;
        
        //std::move(str)是将亡值,但变量b是左值
        string&& b = std::move(str);  
    	return 0;
    }

    move函数的经典误用:

    String s1("hello world");
    String s2(move(s1));
    String s3(s2);
    

            move将s1转化为右值后,在实现s2的拷贝时会使用移动构造,此时s1的资源就被转移到s2中了,s1就会成为无效字符串;

    四,完美转发

            以下PerfectForword为转发的模板函数,Func为实际目标函数,但转发不算完美;完美转发是将参数按传递给PerfectForword函数的实际类型转发给目标函数,而不产生额外开销,就像不存在转发者一样;

    void Func(int x){cout << x << endl;}
    
    template<typename T>
    void PerfectForward(T t)
    {
        //目标函数
        Func(t);
    }

    完美转发是指在函数模板中,完全依照模板的参数类型,将参数传递给函数模板中调用的另一个函数,同时保持其值类别(lvalue或rvalue)和类型不变;

    所谓完美,即模板函数在向其他函数传递自身形参时:

    • 如相应实参是左值,就应被转发为左值;如相应实参是右值,就应该被转发为右值;
    • 为保留对转发而来的参数的左右值属性进行不同处理;
      • 如参数为左值时拷贝语义,参数为右值移动语义;

    通用引用,即可绑定左值也可绑定右值;

    • 如果传入左值结果为左值引用,T 推导为 T&,T&& 折叠为 T&;

    • 如果传入右值结果为右值引用,T 推导为 T,T&& 保持 T&&;

    // 右值引用 - 只能绑定到右值
    void process(string&& str) {}  // 明确的右值引用
    
    // 通用引用 - 可以绑定到左值和右值
    template<typename T>
    void PerfectForward(T&& t) {}  // 可能是左值引用或右值引用

    引用折叠规则

    • T& & 折叠为 T&
    • T& && 折叠为 T&
    • T&& & 折叠为 T&
    • T&& && 折叠为 T&&
    template<typename T>
    void func(T&& param) //这里会发生引用折叠
    {
        // 检查 T 的具体类型
        if constexpr (std::is_same_v<T, int>)
            { std::cout << "T 被推导为: int" << std::endl; }
        else if constexpr (std::is_same_v<T, int&>)
            { std::cout << "T 被推导为: int&" << std::endl; }
        else if constexpr (std::is_same_v<T, const int&>)
            { std::cout << "T 被推导为: const int&" << std::endl; }
    
        // 检查最终参数类型
        if constexpr (std::is_same_v<decltype(param), int&>) 
            { std::cout << "param 类型: int&" << std::endl; }
        else if constexpr (std::is_same_v<decltype(param), const int&>)
            { std::cout << "param 类型: const int&" << std::endl; }
        else if constexpr (std::is_same_v<decltype(param), int&&>) 
            { std::cout << "param 类型: int&&" << std::endl; }
        std::cout << std::endl;
    }
    
    int main() {
        int x = 10;
        const int cx = 20;
    
        func(x);
        func(cx);
        func(30);
    }
    调用实参类型实参值类别T推导结果T&&类型引用折叠过程最终param类型原因
    func(x)int左值int&int& &&& + && → &int&必须保持左值性
    func(cx)const int左值const int&const int& &&& + && → &const int&必须保持左值性和常量性
    func(30)int右值intint&&无折叠int&&普通类型就足够匹配右值

    forward函数

    • 如arg不是左值引用,则返回arg的右值引用;
    • 如arg是左值引用,则返回arg(不修改其类型);
    • 辅助函数,将右值引用完美转发到其他函数;
      • 因为所有有名字的引用变量本身都是左值,即使是右值引用;
      • 右值引用类型不等于是右值;
    • 任何实例化都必须显式指定T的类型(任何隐式推断的T都不匹配);
    //均返回
    static_cast<decltype(arg)&&>(arg)
    //C++11通过forward函数来实现完美转发!
    void Fun(int& x) { cout << "int& -> lvalue ref" << endl; }
    void Fun(int&& x) { cout << "int&& -> rvalue ref" << endl; }
    void Fun(const int& x) { cout << "const int& -> lvalue ref" << endl; }
    void Fun(const int&& x) { cout << "const int&& -> rvalue ref" << endl; }
    
    template<typename T>
    void PerfectForward(T&& t) { //万能引用,即可传递左值也可传递右值
    	Fun(std::forward<T>(t));
    }
    
    int main() {
    	PerfectForward(10); //10是右值,int&& -> rvalue ref
    
    	int a;
    	PerfectForward(a); //a是左值,int& -> lvalue ref
    	PerfectForward(std::move(a)); //将a转化为右值 int&& -> rvalue ref
    
    	const int b = 8;
    	PerfectForward(b); //b是const左值 const int& -> lvalue ref
    	PerfectForward(std::move(b)); //将b转化为const右值 const int&& -> rvalue ref
    	return 0;
    }
    // PerfectForward(10); 此语句推导过程:
    1,依据传递的实参10为字面量右值,根据引用折叠规则
        推导模板函数void PerfectForward(T&& t)的 T 类型为 int
        // 模板实例化为:
        void PerfectForward(int&& t) {
            Fun(std::forward<int>(t));
        }
    
    2,int&& t变量t为右值引用类型,值类别为左值
        std::forward<int>(t)已显式指定类型为int
        static_cast<decltype(arg)&&>(arg)
      -> static_cast<int&&>(t)
      -> 表明将左值t转化为右值

    右值引用作用

    C++98中引用作用,因为引用是别名,需要用指针操作的地方,可以使用引用来替代,可提高代码的可读性及安全性;

    C++11中右值引用主要有以下作用:

    • 给中间临时变量取别名;
    • 实现移动语义(移动构造或移动赋值);
    • 实现完美转发,通过万能引用和引用折叠机制实现的;

    【C++】右值引用详解(移动构造、移动赋值、万能引用和完美转发、关键字default和delete) 右值引用总结 阅读详情

    相关推荐

    C++ 左值、右值、左值引用、右值引用

    本文介绍C++11的各种引用的概念,理解清楚各种引用的概念,非常有助于理解基于c11引用的各种操作。

    baiiu 1205

    详解—C++右值引用

    而临时对象也是右值,因此在用临时对象构造s3时,也采用移动构造,将临时对象中资源转移到s3中,整个过程,只需要创建一块堆内存即可,既省了空间,又大大提高程序运行的效率。2. const修饰的常量,不可修改,只读类型的,理论应该按照右值对待,但因为其可以取地址(如果只是const类型常量的定义,编译器不给其开辟空间,如果对该常量取地址时,编译器才为其开辟空间),C++11认为其是左值。C++98中引用作用:因为引用是一个别名,需要用指针操作的地方,可以使用指针来代替,可以提高代码的可读性以及安全性。

    weixin_55582891的博客 5263

    C++11 新特性 ② | 左值、左值引用、右值与右值引用

    详细讲述左值、左值引用、右值与右值引用相关概念。

    dvlinker的技术专栏 1万+

    C++11特性——右值引用

    首先介绍下左右值(我发现自己学了好长时间都没有对两者进行区分~)对于左值、右值可以简单的以放在等号左右为区分,等号左边的是左值,等号右边的是右值。再来详细的介绍下各自的特点:左值:1)左值可以取地址2)左值可以修改3)左值可以放在等号左右两边右值:1)右值不可以取地址2)右值不可以直接修改3)右值只能放在等号右边4)右值往往是没有名称的再来举几个实例:左值举例:int a;int a = 3;上面的a都是左值纯右值、将亡值。...

    gls_nuaa的博客 7040

    GD32F303定时器配置:实现两路互补PWM输出与相位控制

    本文详细解析了基于GD32F303定时器实现两路互补PWM输出与精确相位控制的方法。通过配置TIMER2的中间对齐模式,结合REMAP功能解决引脚复用问题,从硬件层面稳定生成相位差180度的互补PWM信号,适用于电机驱动、开关电源等对时序要求苛刻的应用场景。

    weixin_29182481的博客 303

    软件工程导论实践:从需求到架构的机票预订系统全流程解析

    本文深入解析机票预订系统从需求分析到架构设计的全流程实践,涵盖业务流程、功能建模、模块化设计、性能优化等关键环节。通过实际项目经验,分享软件工程导论在复杂系统开发中的应用技巧,包括数据流图绘制、E-R图设计、微服务架构及高并发处理等实战策略,助力开发者构建高效可靠的机票预订系统。

    weixin_29202213的博客 412

    右值引用及其作用

    什么是左值、右值? 可以出现在=号左边的则为左值,否则为右值。可以出现在=左边,意味着一定能保存数据,存放在内存中,有实际的内存地址,而右值则是一个临时中间存放的数据,是存放在寄存器中的。 inta = 9, b = 8; a = 8, b = 0; // a,b为左值 // a + 4 = 5; // 错误 a + 4为右值,a + 4为一个临时对象 // -a = 4; // 错误 -a为右值,为一个临时对象 (a) = 5; ...

    caojianfa969的博客 1万+

    最新打赏系统打赏源码麒麟最新打赏源码喜盈门打赏知识付费课程教程直播讲解

    打赏源码打赏系统

    qq_41095398的博客 2029

    【C++进阶】C++11的新特性—右值引用和移动语义

    本文介绍了C++中左值和右值的概念及区别,重点讲解了左值引用和右值引用的语法特性与应用场景。文章首先通过示例代码区分了左值(可寻址)和右值(不可寻址),然后详细分析了引用类型对参数匹配的影响。特别强调了右值引用的设计意义:通过move语义延长临时对象生命周期并支持修改,同时解释了右值引用变量在表达式中具有左值属性的特殊设计。最后指出引用折叠等更深入的内容将在后续探讨。全文通过代码示例和图示帮助理解这些关键概念及其底层实现原理。

    Linux、C++、图形软件开发等。不一定每次都能写出完美的代码,但会认真搞懂每一个问题。 1283

    智能座舱音频系统集成与调试:从芯片选型到音质优化实战

    在智能座舱域控制器架构中,音频系统已从简单的功放加扬声器演进为SoC、数字音频总线、外部DSP与多通道功放协同的复杂子系统。TDM总线的时隙分配、PDM麦克风阵列的信号完整性,以及AEC回声消除算法如何与硬件协同,直接决定多音区体验和语音交互的可靠性。工程实践中,音频调试的关键在于先理顺供电、接地、时钟与数据路由,再针对功放削波、采样率失配、TDM slot错位等典型问题进行系统性排查。从芯片选型到系统级指标验收,只有将音频链路视为整车电子电气架构的一个协同整体,才能真正实现从“响”到“好听”的跨越。本文结

    weixin_30162121的博客 364

    基于 Qt C++ 的智能工厂数字孪生系统

    你想要实现一个基于 Qt C++ 的智能工厂数字孪生系统,核心是 **Qt 3D** 场景搭建 + **实时数据驱动** 设备模型。下面我将为你提供一个完整的解决方案,包含 **核心思路、实现步骤、完整代码示例** 和 **注意事项**。| **渲染层** | 3D 场景搭建、设备模型加载、实时动画渲染、用户交互。| **业务逻辑层** | 数据处理(滤波、转换)、设备状态管理、动画逻辑控制。| **数据层** | 实时采集设备数据(如传感器、PLC、MES 系统),提供数据接口。

    寒寒豆豆软件公司的博客 193

    C++进阶—C++11新特性(移动语义&&右值引用&&可变参数模板&&lambda表达式&&function包装器&&bind函数)

    在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了 C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞 进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。

    IfYouHave的博客 1254

    【数据集】中国陆地生态系统通量观测网 ChinaFLUX

    【数据集】中国陆地生态系统通量观测网 ChinaFLUX

    WW、forever的博客 187

    c++ 右值引用和完美转发(转)

    C++11的右值引用 如下主要讲了引用折叠,但是注意,文章中有不少错误 https://blog.youkuaiyun.com/u014351125/article/details/84502427

    silver9886的专栏 204

    损失函数大汇总(四十三)(Boundary Loss附公式推导与代码)

    摘要 Boundary Loss是一种针对图像分割任务的边界优化损失函数,特别适用于小目标、细长结构和类别不平衡场景。它通过引入真实边界的有符号距离场(SDF),将边界距离优化问题转化为区域积分形式。与Dice Loss等区域重叠损失不同,Boundary Loss更关注预测边界与真实边界的精确对齐,而非整体区域重叠。其核心公式为像素级SDF值与预测概率的乘积求和,通过梯度调整使预测概率在真实边界内部升高、外部降低。该损失通常与区域型损失(如CE或Dice)联合使用,形成"区域分割+边界修正&qu

    悦学共鸣,温柔以待,汇聚光芒,共同成长 354

    TMS_WebGMaps_1.9.8.0_Full_Source

    TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

    详解 C++ 左值、右值、左值引用以及右值引用

    主要讲解了 C++11 的右值引用(及其支持的移动语义和完美转发)。

    Butayarou的博客 2万+

    win10 跳过U8环境检测的IE WebControls.rar

    win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

    C++11 左值、右值、右值引用详解

    左值、右值在C++11中所有的值必属于左值、右值两者之一,右值又可以细分为纯右值、将亡值。在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值(将亡值或纯右值)。

    Hyman's Blog 4万+

    IEM模型,地表粗糙度模拟

    利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

    Data-Structures-and-Algorithm-Analysis-in-Java.pdf

    作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

    【C++11】右值引用

    C++11右值引用

    A.的博客 2013

    【C++】C++11新特性—右值引用,来看看怎么个事儿

    传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。

    小羊的博客 4262

    【C++】C++11右值引用

    今天我们正式进入C++11的学习,C++11引入的一个非常重要的语法就是右值引用,在C++11之前的C++版本我们所提的引用都是左值引用,那么右值引用与左值引用又有什么区别呢?什么是左值?什么是右值?右值引用的价值体现在哪里?那么接下来我们就来学习有关右值引用的相关知识。

    ℉f的博客 2247

    《C++进阶之C++11》【列表初始化 + 右值引用】

    本文摘要: 文章介绍了C++11引入的列表初始化和右值引用两大特性。文中通过代码示例展示了列表初始化在数组、结构体和容器中的实际应用,并对比了C++98与C++11的初始化差异。这些特性显著提升了C++代码的简洁性和性能,是现代化C++编程的重要基础。

    序属秋秋秋的博客 1728

    C++11——右值引用

    前言 在C++98中也有一个引用,为左值引用,但是左值引用有一些不足。而C++11的右值引用的提出弥补了左值引用的不足。 左值引用和右值引用都是别名。 说明:下面说引用都代表C++98的左值引用。 一.右值引用的概念 右值引用也是一块空间的别名。只能对右值进行引用。使用是在类型后面加两个&&。 #include<iostream> using namespace std; int Add(int x,...

    weixin_57023347的博客 9488

    【C++】C++11语法之右值引用

    关于C++11新语法的一些理解以及对其中右值引用的使用的讲解。

    jhao的博客 5609

    左值引用和右值引用

    1.左值和右值 在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值(将亡值或纯右值)。 举个例子,int a = b+c, a 就是左值,其有变量名为a,通过&a可以获取该变量的地址;表达式b+c、函数int func()的返回值是右值,在其被赋值给某一变量前,我们不能通过变量名找到它,&(b+c)这样的操作则不会通过编译。 左值是可以放在赋值号左边可以被赋值的值;左值必须要在内存中有实体; 右值当在赋值号右边取出值赋给其他变量的值;右值可以在内存也可以在CPU寄存

    qq_41181857的博客 8896

    【C++学习】C++11——新特性 | 右值引用 | 完美转发

    介绍了C++11的一些新特性,如列表初始化,以及一些语法糖,最重要的是介绍了右值引用的原理及意义,以及应用场景,从而引出的移动构造和移动赋值函数,还介绍了完美转发,万能引用等内容,以及几个新的关键字。

    weixin_63726869的博客 2058
    上一篇: C++进阶 —— lambda表达式(C++11新特性)
    下一篇: C++进阶 —— 其他(C++11新特性)
    挨代码
    博客等级 码龄5年 1696粉丝 384原创
    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    个

    红包个数最小为10个

    元

    红包金额最低5元

    当前余额3.43元 前往充值 >
    需支付:10.00元
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付元
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值