看 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. SQLServer备份恢复的总结-同名恢复与异名恢复

    SQLServer备份恢复的总结 前言 GUI 搞一把. 命令行太多了也没人看 自己还能省点心 备份 备份数据库建议一定要选择: 备份选项中的 压缩->压缩备份 历史经验一个7.6G的数据库能够 ...

  2. FIO的再学习-不同Raid,不同磁盘性能验证

    FIO的再学习-不同Raid性能验证 背景 发现自己对iodepth的和num_jobs的理解存在偏差 找了一些资料才发现自己很多地方做的不对. 这里找到一个新资料可以进行模拟数据库的测试 测试配置文 ...

  3. [转帖]Linux-计算毫秒数

    https://www.cnblogs.com/yeyuzhuanjia/p/15822653.html date +%s返回自划时代以来的秒数. date +%s%N返回秒数+当前纳秒数. 因此,e ...

  4. [转帖]013 Linux 搞懂「文件所属者更改及权限的赋予」从未如此简单 (chmod、chgrp、chown)

    https://my.oschina.net/u/3113381/blog/5435014   01 一图详解「ls -l」 02 两种符号区分表示文件和目录 -(横线) # 表示非目录文件 d # ...

  5. [转帖]exec系统调用

    https://www.jianshu.com/p/3bf14f7d889c 进程的执行(exec) execve ececve系统调用可以将新程序加载到调用进程的内存空间,在这一过程中,将丢弃现有的 ...

  6. MYSQL 日志参数与性能的关系

    1. 先看一下mysql技术内幕 innodb存储引擎的一个结果 以及各个参数的含义

  7. Linux 通过yum 方式离线下载依赖rpm包的操作步骤

    离线下载依赖rpm包的方法 1.简单获取依赖关系 yum deplist rpm-build 注意 deplist 为依赖项目 我在arm 上面简单跑一下结果为 package: rpm-build- ...

  8. pytest-数据驱动

    今天介绍两种实现数据驱动的方法,json和excel,我们以获取企业微信token接口为例,共 有两个参数corpid&corpsecret 一.json 方法一:@pytest.mark.p ...

  9. K3S +Helm+NFS最小化测试安装部署只需十分钟

    作者:郝建伟 k3s 简介 官方文档:k3s 什么是k3s k3s 是一个轻量级的 Kubernetes 发行版 它针对边缘计算.物联网等场景进行了高度优化. k3s 有以下增强功能: 打包为单个二进 ...

  10. 【JS 逆向百例】医保局 SM2+SM4 国产加密算法实战

    关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...