看 SO 上有一个比较奇怪的问题,

问题代码:

ClassX c = std::move(object_c);  // Invokes move constructor

ClassX&& cr = std::move(object_c);
ClassX c = cr; // Invokes copy constructor

题主的疑问:cr 是右值了,为什么 `ClassX c = cr` 会触发拷贝构造,而不是移动构造

对此的解释:

If it has a name, it's an lvalue. cr is a name, it's an lvalue.

the code should do ClassX c = std::move(cr);. Keep in mind that std::move does not itself move anything, it only allows a move to occur as-if the variable were an unnamed temporary (such as a return value or result of an expression). It also allows a variable to be bound to an rvalue reference (usually something that is useful for parameter passing). If you find this to be confusing, you are not alone; it is confusing.

我测试的 demo:

#include <iostream>

class A {
public:
A() { std::cout << "Constructors" << std::endl; } A(const A& a) { std::cout << "Copy Constructors" << std::endl; } A& operator=(const A& a) {
std::cout << "Assignment Operators" << std::endl; return *this;
} A& operator=(const A&& a) {
std::cout << "Move Assignment Operators" << std::endl;
return *this;
}
}; int main() {
A a; // Constructors
A a_5; // Constructors
A a_6; // Constructors A&& a_1 = std::move(a); // 没有提示
A& a_2 = a; // 没有提示 A a_7 = a_1; // Copy Constructors
A a_3 = a; // Copy Constructors
A a_4(a); // Copy Constructors
A a_8 = std::move(a); // Copy Constructors a_6 = a_1; // Assignment Operators
a_5 = a; // Assignment Operators
a_1 = a_8; // Assignment Operators a_6 = std::move(a_1); // Move Assignment Operators return 0;
}

  

std::move

  • std::move 是一个函数模板,用于将一个左值转换为右值引用,从而告诉编译器允许在之后的操作中对该值进行移动语义的操作。
  • 移动语义是 C++11 引入的特性,它允许在不拷贝的情况下将对象的资源(比如动态分配的内存)转移给其他对象,提高了性能。
  • std::move 并不会真正移动数据,它只是将对象标记为“可以移动”,使得在后续操作中调用移动构造函数或移动赋值运算符。
  • 使用 std::move 的目的是告诉编译器你希望使用移动语义,但要注意,使用之后原来的对象可能处于有效但未定义的状态。

移动构造函数和移动赋值运算符写法如下:

class MyClass {
public:
// 移动构造函数
MyClass(MyClass&& other) {
// 将资源从 other 移动到当前对象
// ...
}
}; class MyClass {
public:
// 移动赋值操作符
MyClass& operator=(MyClass&& other) {
// 将资源从 other 移动到当前对象
// ...
return *this;
}
};

MyClass(MyClass&&) - 移动构造函数:

  • MyClass(MyClass&&) 是一个移动构造函数。它接受一个右值引用作为参数,允许将一个临时对象的资源(如堆上分配的内存)移动到新创建的对象中。
  • 移动构造函数通常用于在创建新对象时避免不必要的资源拷贝,从而提高性能。例如,在 C++11 中,容器在进行元素插入时可以使用移动构造函数来避免额外的拷贝操作。
  • 移动构造函数通常不会修改源对象的状态,而是将源对象的资源所有权转移给新对象。

MyClass& operator=(MyClass&&) - 移动赋值操作符:

  • MyClass& operator=(MyClass&&) 是一个移动赋值操作符。它用于将一个右值引用的对象的资源(如堆上分配的内存)移动到另一个对象中。
  • 移动赋值操作符用于在赋值操作时避免不必要的资源拷贝,从而提高性能。它可以被用于自定义移动赋值,以实现在赋值时的资源转移。

移动构造函数用于创建新对象并从右值引用中获取资源,而移动赋值操作符用于将资源从一个右值引用的对象移动到另一个对象中

C++ std::move 的一些问题的更多相关文章

  1. C++ 11中的右值引用以及std::move

    看了很多篇文章,现在终于搞懂了C++ 中的右值以及std::move   左值和右值最重要的区别就是右值其实是一个临时的变量 在C++ 11中,也为右值引用增加了新语法,即&&   比 ...

  2. std::move()和std::forward()

    std::move(t)负责将t的类型转换为右值引用,这种功能很有用,可以用在swap中,也可以用来解决完美转发. std::move()的源码如下 template<class _Ty> ...

  3. C++ 11 右值引用以及std::move

    转载请注明出处:http://blog.csdn.net/luotuo44/article/details/46779063 新类型: int和int&是什么?都是类型.int是整数类型,in ...

  4. std::move()

    #include <iostream> #include <utility> #include <vector> #include <string> i ...

  5. C++11右值引用和std::move语句实例解析

    关键字:C++11,右值引用,rvalue,std::move,VS 2015 OS:Windows 10 右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一.从实践 ...

  6. c++ 11 移动语义、std::move 左值、右值、将亡值、纯右值、右值引用

    为什么要用移动语义 先看看下面的代码 // rvalue_reference.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #includ ...

  7. C++ 11 左值,右值,左值引用,右值引用,std::move, std::foward

    这篇文章要介绍的内容和标题一致,关于C++ 11中的这几个特性网上介绍的文章很多,看了一些之后想把几个比较关键的点总结记录一下,文章比较长.给出了很多代码示例,都是编译运行测试过的,希望能用这些帮助理 ...

  8. C++11 std::move和std::forward

    下文先从C++11引入的几个规则,如引用折叠.右值引用的特殊类型推断规则.static_cast的扩展功能说起,然后通过例子解析std::move和std::forward的推导解析过程,说明std: ...

  9. item 23: 理解std::move和std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 根据std::move和std::forward不 ...

  10. Item 25: 对右值引用使用std::move,对universal引用则使用std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 右值引用只能绑定那些有资格被move的对象上去.如 ...

随机推荐

  1. [转帖]windows10彻底关闭Windows Defender的4种方法

    https://zhuanlan.zhihu.com/p/495107049 Windows Defender是windows10系统自带的杀毒软件.默认情况下它处于打开的状态.大多数第三方的杀毒软件 ...

  2. [转帖]Oracle与防火墙

    https://www.laoxiong.net/oracle_and_firewall.html 老熊 Oracle数据库管理 2009-04-20 最近有两次Oracle数据库故障与防火墙有关.这 ...

  3. [转帖]《Linux性能优化实战》笔记(十五)—— 磁盘IO的工作原理

    前一篇介绍了文件系统的工作原理,这一篇来看看磁盘IO的工作原理 一. 磁盘 1. 按存储介质分类 磁盘是可以持久化存储的设备,根据存储介质的不同,常见磁盘可以分为两类:机械磁盘和固态磁盘. 机械磁盘, ...

  4. [转帖]解决vCenter6.x由于证书过期问题无法登录

    https://www.dinghui.org/vcenter-sts-certificate.html#:~:text=%E8%BF%99%E6%97%B6%E5%80%99%EF%BC%8C%E5 ...

  5. [转帖]原创经典:SQLSERVER SendStringParametersAsUnicode引发的疑案 推荐

    https://developer.aliyun.com/article/429563 简介: 上周五碰到开发的请求协助解决数据预定程序中对单头等几个表检索数据时检索条件尾数是9的数据特别慢.第一时间 ...

  6. CentOS firewall简单总结

    CentOS firewall简单总结 简介 防火墙是安全的重要道防线. 硬件防火墙一般部署再内网的边界区域.作为最外层的防护. 但是一般硬件的防火墙会比较宽松. 不然会导致很多业务不可用 软件防火墙 ...

  7. 当你对 redis 说你中意的女孩是 Mia

    作者:京东科技 周新智 一.Redis 众所周知,Redis = Remote Dictionary Server,即远程字典服务. 是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久 ...

  8. 【计数,DP】CF1081G Mergesort Strikes Back

    Problem Link 现有一归并排序算法,但是算法很天才,设了个递归深度上限,如果递归深度到达 \(k\) 则立即返回.其它部分都和正常归并排序一样,递归中点是 \(\lfloor (l+r)/2 ...

  9. 在k8s中的控制器和部署服务-ReplicationController和ReplicaSet

    pod 代表了 k8s 中的基本部署单元,但是在实际应用场景中,服务不可能是单个pod运行的,否则会出现"单点".在 k8s 中对 pod 的托管部署,专门抽象成了单独的资源.其中 ...

  10. 在K8S中,Pod重启策略有哪些?

    在Kubernetes(简称K8s)中,Pod的重启策略定义了当容器失败时kubelet如何处理.有三种主要的重启策略: Always: 这是默认的重启策略.如果设置了为"Always&qu ...