首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

现代 C++:右值引用移动语意、完美转发

右值引用,简单说就是绑定在右值引用。右值的内容可以直接移动(move)给左值对象,而不需要进行开销较大的深拷贝(deep copy)。...每次执行移动语意,是分别调用 s_ 和 v_ 的移动语意函数——理论只需要对内部指针进行修改,所以效率较高。...到底什么时候是左值?什么时候是右值?是不是有点混乱? C++ 中,每个表达式(expression)都有两个特性: has identity? —— 是否有唯一标识,比如地址、指针。...有唯一标识的表达式 C++ 中被称为 glvalue(generalized lvalue)。 can be moved from? —— 是否可以安全地移动(编译器)。...不过就算不是特别清楚这些概念,也不影响我们对移动语义的利用。 参考文档 维基百科:右值引用 Value categories

2.3K20

探究C++11智能指针之std::unique_ptr

std::unique_ptr系C++11引入的智能指针,拥有资源的唯一所有权,头文件 #include 。...unique_ptr指针指向的堆内存空间的引用计数为 1,如果unique_ptr 指针放弃对所指堆内存空间的所有权,那么该空间会被立即释放回收。 那么,什么时候使用unique_ptr呢?...std::unique_ptr禁止复制语义 和 std::shared_ptr区别:unique_ptr是移动构造(unique_ptr不可拷贝和赋值,但可以被移动,unique_ptr禁止复制语义,拷贝构造函数和复制运算符...unique_ptr up = clone(num); return 0; } std::unique_ptr与std::move不解之缘 std::unique_ptr无法被复制,但可以使用移动构造将...答案是否定的,只有实现了移动构造函数移动运算符的类才可以。恰恰std::unique_ptr实现了二者。

2K10
您找到你想要的搜索结果了吗?
是的
没有找到

为什么我应该使用指针而不是对象本身

回答 对于现代 C++ (尤其是 C++ 11 之后),大量使用 new 动态分配是不明智的选择。 下面从两个方面来解释: 什么时候使用 new? 什么时候使用指针?...当你确实要用动态内存分配的话,我们应该用智能指针或者其它的 RAII 技术来管理这部分资源。 什么时候使用指针? 不过,除了动态分配内存之外,原始指针还有其它用途。...引用语义(reference semantics): 有的时候,你希望函数传递进来的参数不是一份副本(copy),因为创建副本的代价很大。这个时候,你就可以通过指针。...不过 C++ 11 已经有了移动(move)语义,这个问题就不用担心了。 多态(polymorphic): 对于多态类型,指针引用可以避免对象被切片(slice)。...切片的意思就是说:函数传参处理多态变量时,如果一个派生类对象向上转换(upcast),用的是传值的方式,而不是指针引用,那么,这个派生类对象 upcast 以后,将会被 slice 成基类对象,

1.3K10

CC++面试题之语言基础篇(一)

存储静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。 static的第三个作用是默认初始化为0.和全局变量一样存储静态数据区。 说说静态变量什么时候初始化?...从所在空间考虑:除了局部变量外,其他都在静态存储区。...)+移动语义 完美转发(Perfect Forwarding):右值引用允许函数参数中精确传递参数的值类别(左值右值)。...移动语义(Move Semantics):移动语义允许将资源从一个对象移动到另一个对象,而不是进行昂贵的数据复制。...c++中A类访问B类中的私有成员的解决方法 使用友元函数友元类:B类中声明A类为友元,或者A类中声明B类为友元 提供公有成员函数接口:如果希望B类的私有成员被A类间接访问,可以B类中提供一些公有成员函数接口

15410

C++智能指针详解(共享指针唯一指针,自动指针

前言:智能指针C++11中引入,分为三类: shared_ptr:共享指针 unique_ptr:唯一指针 auto_ptr:自动指针 一、共享指针 几个共享指针可以指向同一个对象; 每当shared_ptr...语句不需要move()的原因是C++11规定编译器将自动尝试移动 5.使用唯一指针处理数组 unique_ptr uq(new string[666]); cout << uq[0...obj; } }; int main() { unique_ptr up(new ClassA()); return 0; } 唯一指针引用的对象销毁时需要进行除...void(*)(T *) function 使用decltype 三、自动指针 C++98中存在,于C++11中使用唯一指针替换其它 四、智能指针接口汇总 API Name...将所有权转移到sp) sp = move(up) 使用unique_ptr进行移动赋值(up将所有权转让给sp) sp = move(ap) 使用auto_ptr进行移动赋值(ap将所有权转让给sp)

1.5K20

【C++11特性篇】探究【右值引用(移动语义)】是如何大大提高效率?——对比【拷贝构造&左值引用

【左值&左值引用】和【右值&右值引用】基础知识 相关基础知识知识点在YY的这篇博客中有详细说明:传送门 二.普通传值返回 关于 深浅拷贝 ,YY的这篇博客里有详细的介绍:传送门->【C++】STL容器...; return 0; } 2)左值引用的缺陷: 但是当函数返回对象是一个 局部变量,出了函数作用域就不存在了,就不能使用左值引用返回, 只能传值返回。...四.右值与移动语义移动构造&移动赋值)对比【普通传值】 1)简述【移动构造】+ 结合代码演示 移动构造本质是将参数右值的资源窃取过来,占为已有 ,那么就不用做深拷贝了 所以它叫做移动构造,就是 窃取别人的资源来构造自己...】 过程2:再对临时对象再次进行一次 【移动构造】赋给目标对象;其指针相应也置空 一共完成 2次 移动构造 5)C++11中,什么时候【拷贝构造】?...什么时候移动构造(右值引用)】?

9410

如何设计一个C++的类?

tips:编译器某些情况下会生成移动构造函数移动赋值运算符,但记住这些情况太麻烦了,建议手动控制,明确要的时候就自己写一个,明确不要的时候就delete掉。...一个类具有移动构造函数才具备移动语义,如果追求资源管理的效率,move资源效率一般会比拷贝一个资源高一些。...函数传参无非就是传值还是传引用的选择问题: 参数需要在函数内修改,并在函数外使用修改后的值时:传引用 参数需要在函数内修改,但在函数外使用修改前的值时:传值 参数函数内不会修改,参数类型如果为基础类型...暴露给用户的头文件要想清楚该暴露什么,不该暴露什么,外部头文件不要引用内部头文件 类成员变量确保作保初始化工作 不要让异常逃离析构函数 构造函数析构函数不要调用虚函数 不要返回函数局部对象的指针引用...尽量不要返回函数内部堆对象的指针引用,容易产生内存泄漏,尽量遵循谁申请谁释放的原则 ?

1.5K20

还分不清左值,右值,将亡值?看这里!

它们事实上表征了表达式的属性,而这种属性的区别主要体现在使用上,如能否做运算符的左操作数、能否使用移动语义(关于移动语义,在下的后续文章中会详细介绍)等。...举例来说, 函数名和变量名(实际是函数指针和具名变量,具名变量如std::cin、std::endl等)、返回左值引用的函数调用、前置自增/自减运算符连接的表达式++i/--i、由赋值运算符复合赋值运算符连接的表达式...,会调用移动构造函数移动赋值运算符⑤来移动资源,从而避免拷贝,提高效率(关于这些知识,在后续文章讲移动语义时,会详细介绍)。...附注 事实,将亡值不过是C++11提出的一块晦涩的语法糖。它与纯右值功能上及其相似,如都不能做操作符的左操作数,都可以使用移动构造函数和移动赋值运算符。...③当我们将函数名作为一个值来使用时,该函数名自动转换为指向对应函数的指针。 ④关于右值引用本身,没什么可说的,就是指可以绑定到右值引用,用"&&"表示,如int &&rra=6;。

4.8K30

Rust 编程学习笔记Day 3-变量所有权及生命周期

栈上有一个包含长度和容量的指针指向堆上的内存。...按大多数编程语言的做法,现在 data 就有2个引用了。且每当把data作为参数传递一次,就会多一个引用。 那么问题来了:堆上的内存什么时候释放? C/C++:手动处理释放,占用码农心智。...之前我们开发的时候,引用是一种随意、可隐式产生的行为。比如C语言里到处乱飞的指针。比如Java里随处可见的按引用传参。而Rust决定限制开发者随意引用的行为。...所有权和Move的语义 如何保持独占?要考虑的情况还是比较多的。可能造成这个变量的拥有者不唯一。比如以下情况: 变量A被赋给 变量B。 变量A作为参数被传递给函数C。 作为返回值从函数D返回。...这是因为我们在打印data1的时候,data1实际已经在上面调用sum(data1)的时候。所有权已经转移(move)到sum()里了。所以后面就不能使用了。

54040

C++的智能指针unique_ptr、shared_ptr和weak_ptr

指针语义:unique_ptr的使用方式与原始指针相似,可以通过指针操作符(->)和解引用操作符(*)来访问所指向对象的成员。...这是为了确保独占所有权的特性,防止多个指针同时管理同一个对象的内存。 支持移动语义:unique_ptr支持移动构造和移动赋值操作,可以将所有权转移给新的unique_ptr,而无需进行内存拷贝。...指针语义:shared_ptr的使用方式与原始指针相似,可以通过指针操作符(->)和解引用操作符(*)来访问所指向对象的成员。 可拷贝:shared_ptr是可拷贝的,即可以进行复制构造和赋值操作。...循环引用问题 循环引用问题指的是使用shared_ptr管理对象时,存在两个多个对象相互持有shared_ptr,形成一个循环引用的情况。...通过弱引用指针,我们可以需要时使用lock()函数获取一个有效的shared_ptr来操作对象,一旦对象的引用计数变为0,弱引用指针将自动失效。

38220

左值引用与右值引用

---- 引言:如何区分左值和右值 ①左值 左值是一个表示数据的表达式(如变量名引用指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。...C++11中,std::move()函数位于头文件中,该函数名字具有迷惑性,它并不搬移任何东西,唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义。...&& s) -- 移动语义" << endl; swap(s); return *this; } 一个右值引用神奇的特性(不是右值引用的重点使用场景) 先来看一段代码: int main() {...三、完美转发 模板编程时,由于泛型,未来使用该模板类时,我们不知道引用是右值还是左值引用,再加上左右值引用不能直接复用的原因。...// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力, // 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值, // 我们希望能够传递过程中保持它的左值或者右值的属性

40020

Effective Modern C++翻译(1):序言

想要知道什么时候应该(什么时候不应该)把一个对象声明为auto?对为什么const成员函数应该是线程安全的感兴趣?如何使用std::unique_ptr实现pimpl?...C++11最流行的特性很可能是移动语义移动语义的基础是从表达式中判断是左值右值,这是因为右值暗示了对象有资格使用移动运算,而左值通常不能。...概念(尽管并不总是在实践中)右值相对应于从函数返回的匿名的临时变量,而左值相对应于你可以引用的对象,既可以通过指针,也可以通过引用。...class Widget { public: Widget(Widget&& 这里,widgt的移动构造函数中取得rhs参数的地址是完全合法的,所以rhs是一个左值,尽管它的类型是一个右值的引用...我把参数命名为rhs,代表了right-hand side,这是我使用移动操作(比如移动构造,移动赋值)和拷贝操作(比如拷贝构造,拷贝赋值)时比较偏爱的名字,尽管我使用二元运算符也通常使用rhs作为右面参数的名字

1.2K90

每个C++开发者都应该学习和使用的C++11特性

移动语义的背景: 传统的C++中,对象的赋值和传递通常会进行复制操作,即调用拷贝构造函数拷贝赋值运算符。...右值引用移动语义: 为了解决上述问题,C++11引入了右值引用(Rvalue Reference)和移动语义。右值引用是一种新的引用类型,用于表示对临时对象即将销毁的对象的引用。...通过右值引用,可以识别出临时对象,并且在这些对象应用移动语义移动语义允许将资源从一个对象转移到另一个对象,而不是复制资源。...移动语义使用场景: 容器中插入临时对象: 通过移动语义,可以避免容器中插入临时对象时进行深拷贝,提高了插入的效率。...移动语义的实现: 为了支持移动语义,需要在类中定义移动构造函数和移动赋值运算符,并在这些函数中执行资源的转移操作。同时,也需要标记需要移动的对象为右值引用

4710

Modern C++ 最核心的变化是什么?

右值引用的意义通常解释为两大作用:移动语义和完美转发。本文主要讨论移动语义。 一、移动语义 移动语义,简单来说解决的是各种情形下对象的资源所有权转移的问题。...被移走资源的右值废弃时已经成为空壳,析构的开销也会降低。 右值中的数据可以被安全移走这一特性使得右值被用来表达移动语义。以同类型的右值构造对象时,需要以引用形式传入参数。...上面两种形式分别返回栈的左值和右值,但都适用移动语义(unique_ptr 不支持拷贝)。...v2 = str_split("1,2,3");  注:v 的拷贝构造调用有可能被优化掉,尽管如此语义仍然是有一次拷贝操作。 同样的代码,支持移动语义的世界里就变得更美好了。...v2 = str_split("1,2,3");  注:v 的移动构造调用有可能被优化掉,尽管如此语义仍然是有一次移动操作。 不用多说也知道上面的形式是多么常用和自然。

94821

什么是智能指针

问题 什么是智能指针什么时候用它们? 回答 从较浅的层面看,智能指针其实是利用了 RAII(资源获取即初始化)技术对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针。...但是智能指针还有一重更加深刻的含义,就是把 value 语义转化为 reference 语义。C++ 和 Java 有一处最大的区别在于语义不同。...如果想实现 Java 中的引用语义,就应该使用智能指针,可以参考《C++ 标准库程序》(侯捷/孟岩 译)的第五章讲容器的部分,有一节叫做 “用 Value 语义实现 Reference 语义”,还有陈硕的那本...shared_ptr 和 weak_ptr shared_ptr 是目前工程内使用最多最广泛的智能指针,它使用引用计数实现对同一块内存的多个引用最后一个引用被释放时,指向的内存才释放,这也是和 unique_ptr...可以将 unique_ptr 存储到 STL 容器中,只要不调用将一个 unique_ptr 复制赋给另一个的算法(如 sort())。例如,可在程序中使用类似于下面的代码段。

58120

【专业技术】从4行代码看右值引用

虽然第二行代码和第一行代码看起来差别不大,但是实际语义的差别很大,这里,getVar()产生的临时值不会像第一行代码那样,表达式结束之后就销毁了,而是会被“续命”,他的生命周期将会通过右值引用得以延续...事实C++11为了解决这个问题,提供了std::move方法来将左值转换为右值,从而方便应用移动语义。...使用move几乎没有任何代价,只是转换了资源的所有权。他实际上将左值变成右值引用,然后应用移动语义,调用移动构造函数,就避免了拷贝,提高了程序性能。...这里也要注意对move语义的误解,move实际它并不能移动任何东西,它唯一的功能是将一个左值强制转换为一个右值引用。...如果是一些基本类型比如int和char[10]定长数组等类型,使用move的话仍然会发生拷贝(因为没有对应的移动构造函数)。所以,move对于含资源(堆内存句柄)的对象来说更有意义。

1.5K71

第4章 | 移动

这里遵循了社区的习惯译法“移动”,学过 C++ 的读者可能比较熟悉了;对使用其他语言的读者来说,要特别注意这里的“移动语义并非像真实生活中那样简单地挪动物品的位置,而是涉及一个非常重要的概念——所有权...——译者注 4.2 移动 Rust 中,对大多数类型来说,像为变量赋值、将其传给函数从函数返回这样的操作都不会复制值,而是会移动值。...我们在这个例子中使用了初始化和赋值,因为它们很简单,但 Rust 还将“移动”的语义应用到了几乎所有对值的使用上。...如果将这些技术与 Rc 指针结合使用,则确实可以建立循环并造成内存泄漏。 有时可以通过对某些链接使用引用指针 std::rc::Weak 来避免建立 Rc 指针循环。...移动引用计数指针是缓解所有权树严格性问题的两种途径。第 5 章中,我们将研究第三种途径:借用对值的引用

3610

《逆袭进大厂》第三弹之C++提高篇79问79答

所以派生类实际刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。...指针引用之间如何转换? 1) 向上类型转换 将派生类指针引用转换为基类的指针引用被称为向上类型转换,向上类型转换会自动进行,而且向上类型转换是安全的。...2) 向下类型转换 将基类指针引用转换为派生类指针引用被称为向下类型转换,向下类型转换不会自动进行,因为一个基类对应几个派生类,所以向下类型转换时不知道对应哪个派生类,所以向下类型转换时必须加动态类型识别技术...150、你什么情况用指针当参数,什么时候引用,为什么?...,如内置数据类型或者小型结构,则按照值传递; 如果数据对象是数组,则使用指针唯一的选择),并且指针声明为指向const的指针; 如果数据对象是较大的结构,则使用const指针或者引用,已提高程序的效率

2.2K30

C++的std::move()

std::move()是 C++ 标准库中的一个函数模板,用于将对象转换为右值引用,以便支持移动语义。它位于 头文件中,并且是移动语义的关键工具之一。...它接受一个参数 t 并返回一个右值引用。通过使用 std::move(),可以显式地将左值转换为右值引用。 std::move() 的作用是标记传入的对象为可移动的,而不是进行深拷贝。...这样做可以告诉编译器,我们希望对该对象使用移动语义来实现资源的转移,从而提高代码的性能和效率。...使用 std::move() 后,对象的状态可能会发生改变,即资源的所有权可能会被移动到其他对象中被销毁。...移动语义中,被移动的对象的状态应该处于有效但不确定的状态,即不应该假设对象仍然保持其原有的值。 被移动后的对象通常不应该再被使用,除非它们经过了重新构造赋值操作。

51330

闭关多日,整理一份C++中那些重要又容易忽视的细节

返回引用时,应避免返回函数终止时不再存在的内存单元引用指针里说过同样的话)。 为避免这种问题,最简单的方法就是:返回一个作为参数传递给函数的引用。 ---- 何时使用引用参数? 想用的时候呗。...使用引用参数这种“大招”的主要动机有: 1、程序员能够修改调用函数中的数据对象 2、可以提高程序的运行速度。 那么,什么时候使用指针什么时候使用引用什么时候使用按值传递呢?...对象是数组,指针。这是唯一的选择,并将指针声明为指向const的指针。 数据对象是较大的结构,使用const指针const引用,提高程序效率。 数据对象是类对象,使用const引用。...类设计的语义常常要求使用引用,因此,传递类对象参数的标准方式是按引用传递。 对于修改调用函数中数据的函数: 如果数据对象是内置数据类型,使用指针。 如果对象是数组,只能使用指针。...如果对象是结构,使用指针引用都可以。 如果对象是类对象,使用引用。 ---- 类 控制对成员的访问,是公有?是私有? 对新手来说,这个点估计是经常被忽略的吧。

57010
领券