c++  复制消除问题解决示例详析

 更新时间:2023年08月10日 10:51:01   作者:hedzr  
这篇文章主要为大家介绍了c++  复制消除问题解决示例详析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

错误示范

push_back 这么写是错的:

template<class T>
  class threaded_message_queue {
    public:
    using lock = std::unique_lock<std::mutex>;
    void push_back(T t) {
      {
        lock l(_m);
        _data.push_back(std::move(t));
      }
      _cv.notify_one();
    }
  }
};//

入参 T t 导致了调用者在这里会发生一次临时对象 TMP 的复制,稍后在函数退出点处 TMP 还会被隐式析构。所以这个写法不是良构

至于函数体中的 std::move(t) 也就是聊胜于无了,它并不会让 t 少掉 TMP 的复制,仅仅只是少掉了 t 到 _data 的一次复制而已。

正确工作

做模板类开发时,经常会遇到 push_back 的这种场景。

正确的 push_back 应该包含左值复制和右值移动两种语义,一般来说像是这样子:

template<class T>
  class threaded_message_queue {
    public:
    using lock = std::unique_lock<std::mutex>;
    void emplace_back(T &&t) {
      {
        lock l(_m);
        _data.template emplace_back(std::move(t));
      }
      _cv.notify_one();
    }
    void push_back(T const &t) {
      {
        lock l(_m);
        _data.push_back(t);
      }
      _cv.notify_one();
    }
  }
};

注意右值加上移动语义才是一对搭配。T t 和移动语义在一起只是一种错觉。

你还可以加上一个 push_back 的移动语义:

void push_back(T &&t) {
      {
        lock l(_m);
        _data.template emplace_back(std::move(t));
      }
      _cv.notify_one();
    }

这是因为按照约定,emplace_back 通常采用模板变参并实现 T 类的原位构造。这个话题我在 C++ 中的原位构造函数及完美转发 - 写我们自己的 variant 包装类 已经有过一定的讨论,这里就不详述了。

X-class

hicc::debug::X 是一个专门用来调试 RVO,In-place construction,Copy Elision 等等特性的工具类,它平平无奇,只不过是在若干位置埋点冰打印 stdout 文字而已,这可以让我们直观观察到哪些行为实际上发生了。

X-class 在构造函数的入参部分有相似的构造:

namespace hicc::debug {
    class X {
        std::string _str;
        void _ct(const char *leading) {
            printf("  - %s: X[ptr=%p].str: %p, '%s'\n", leading, (void *) this, (void *) _str.c_str(), _str.c_str());
        }
    public:
        X() {
            _ct("ctor()");
        }
        ~X() {
            _ct("dtor");
        }
        X(std::string &&s)
            : _str(std::move(s)) {
            _ct("ctor(s)");
        }
        X(std::string const &s)
            : _str(s) {
            _ct("ctor(s(const&))");
        }
        X &operator=(std::string &&s) {
            _str = std::move(s);
            _ct("operator=(&&s)");
            return (*this);
        }
        X &operator=(std::string const &s) {
            _str = s;
            _ct("operator=(const&s)");
            return (*this);
        }
        const char *c_str() const { return _str.c_str(); }
        operator const char *() const { return _str.c_str(); }
    };
} // namespace hicc::debug

以上就是c++ 复制消除问题解决示例详析的详细内容,更多关于c++ 复制消除问题的资料请关注脚本之家其它相关文章!

相关文章

  • C++数据结构哈希表详解

    C++数据结构哈希表详解

    C++标准库中使用的unordered_map底层实现是哈希表,下面这篇文章主要给大家介绍了关于C++中使用哈希表(unordered_map)的一些常用操作方法,需要的朋友可以参考下
    2022-07-07
  • C语言驱动开发之通过ReadFile与内核层通信

    C语言驱动开发之通过ReadFile与内核层通信

    驱动与应用程序的通信是非常有必要的,内核中执行代码后需要将其动态显示给应用层。为了实现内核与应用层数据交互则必须有通信的方法,微软为我们提供了三种通信方式,本文先来介绍通过ReadFile系列函数实现的通信模式
    2022-09-09
  • 基于opencv的行人检测(支持图片视频)

    基于opencv的行人检测(支持图片视频)

    本文主要介绍了基于opencv的行人检测(支持图片视频),文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • C语言解决螺旋矩阵算法问题的代码示例

    C语言解决螺旋矩阵算法问题的代码示例

    这篇文章主要介绍了C语言解决螺旋矩阵算法问题的代码示例,螺旋矩阵中的数字由第一行开始到右边不断变大,向下变大,向左变大,向上变大,如此循环...需要的朋友可以参考下
    2016-04-04
  • C++常见的stl容器与相关操作 示例解析

    C++常见的stl容器与相关操作 示例解析

    所谓容器,就是可以承载,包含元素的一个器件,它是STL六大组件之一,是容器、算法、迭代器中最重要也是最核心的一部分
    2022-10-10
  • C++基础入门教程(三):数组、字符串、结构体、共用体

    C++基础入门教程(三):数组、字符串、结构体、共用体

    这篇文章主要介绍了C++基础入门教程(三):数组、字符串、结构体、共用体,需要的朋友可以参考下
    2014-11-11
  • 关于vs strcpy_s()和strcat_s()用法探究

    关于vs strcpy_s()和strcat_s()用法探究

    这篇文章主要介绍了关于vs strcpy_s()strcat_s()用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • 深入解析C++编程中的运算符重载

    深入解析C++编程中的运算符重载

    这篇文章主要介绍了C++编程中的运算符重载,运算符重载是C++入门学习中的基础知识,需要的朋友可以参考下
    2016-04-04
  • C语言中main函数两个参数的作用

    C语言中main函数两个参数的作用

    这篇文章主要介绍了C语言中main函数两个参数的作用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • C++算术运算符与类型转换

    C++算术运算符与类型转换

    这篇文章主要介绍了C++算术运算符与类型转换,C++当中提供5种基础的算术运算符,分别是加法、减法、乘法、除法和取模。下main我们就一起来看看下面文章得具体举例与说明,需要的朋友可以参考一下,希望对你有所帮助
    2021-11-11

最新评论