看 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. SkyWalking的学习之三

    SkyWalking的学习之三 持续优化 SkyWalking 默认可以使用h2,但是感觉容量和性能都可能不太好 所以我想使用一下elasticSearch进行替换. 自己其实一直想心想去学习, 但是 ...

  2. [转帖]麒麟v10上部署TiDBv5.1.2生产环境的最佳实践

    https://tidb.net/book/tidb-monthly/2022/2022-07/usercase/tidb-v5-1-2 前言​ 笔者最近在一个银行项目中做 PoC 测试,由于客户选择 ...

  3. [转帖]金仓数据库KWR使用说明

    金仓数据库KWR使用说明 1.KWR性能报告介绍 2.部署KWR性能报告功能 2.1.修改配置文件 2.2.使配置文件中参数生效 2.3.创建KWR扩展 3.使用KWR快照功能 3.1.创建KWR快照 ...

  4. [转帖]一次SSL握手异常,我发现JDK还有发行版区别

    https://www.cnblogs.com/codelogs/p/16633704.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 最近,我们一个 ...

  5. [转帖]MySQL InnoDB存储引擎大观

      https://baijiahao.baidu.com/s?id=1709263187856706948&wfr=spider&for=pc MySQL InnoDB 引擎现在广为 ...

  6. 是否开启raid卡缓存的影响

    开启raid卡缓存 Write back 对IO性能的影响 背景 公司买了一台服务器. 想进行一下升级 但是因为管理员担心数据丢失, 使用了write through + (raid6 + hotsp ...

  7. Mysql 安装文件下载

    今天上了mysql的官方网站想下载mysql数据库 https://www.mysql.com 注册之后发现 出口许可证的问题 这里fxxk 一下川建国的老婆和女儿 感觉比较抑郁 然后就去百度了下 发 ...

  8. _0x4c9738 怎么还原?嘿,还真可以还原!

    _0x4c9738 变量名还原,噂嘟假嘟? 代码混淆(obfuscation)和代码反混淆(deobfuscation)在爬虫.逆向当中可以说是非常常见的情况了,初学者经常问一个问题,类似 _0x4c ...

  9. NextJs 与 Tailwind 入门开发笔记

    前言 距离上次更新已经过去好久了,之前我在 StarBlog 博客2023年底更新一览的文章里说要使用 Next.js 来重构博客前端,最近也确实用 next.js 做了两个小项目,一个是单点认证项目 ...

  10. kettle系统列文章03---如何建立一个作业

    上篇文章我们建立好了转换,我们希望这个转换可以做成定时任务,每一分钟执行一次 第一步:创建作业开始节点:文件---->新建---->作业----核心对象---->通用-----> ...