为什么使用移动构造函数? clang-tidy modernize-pass-by-value

时间:2016-09-07 17:46:19

标签: c++11 clang c++14

我们正在玩我们的构建上的铿锵声,我遇到了一些我不完全了解它的行为。我会把代码放在第一位,然后再提出问题。

如果我使用以下代码:

#include <iostream>

using namespace std;

class Param {
public:
    Param() {cout << "constructor" << endl;}
    ~Param() {cout << "destructor" << endl;}
    Param(const Param &other) {cout << "copy constructor" << endl;}
    Param(Param&& other) {cout << "move constructor" << endl;}
    Param& operator=(const Param& other) {cout << "copy assignment" << endl; return *this; }
    Param& operator=(Param&& other) {cout << "Param move assignment" << endl; return *this; }
};

class A {
public:
    A(const Param& param) : m_param(param){}
    Param m_param;
};

int main() {
    const Param param;
    A a(param);
}

和这个CMake文件:

cmake_minimum_required(VERSION 3.2)
project(clang)
add_executable(clang main.cpp)
set_property(TARGET clang PROPERTY CXX_STANDARD 14)

生成的二进制文件将输出:

constructor
copy constructor
destructor
destructor

如果我然后像这样在CMake文件上启用clang-tidy:

cmake_minimum_required(VERSION 3.2)
project(clang)
add_executable(clang main.cpp)
set_property(TARGET clang PROPERTY CXX_STANDARD 14)
set_property(TARGET clang PROPERTY CXX_CLANG_TIDY "/usr/bin/clang-tidy;-checks=modernize-*;-fix")

编译将打印以下内容:

/.../main.cpp:17:7: warning: pass by value and use std::move [modernize-pass-by-value]
    A(const Param& param) : m_param(param){}
      ^
/.../main.cpp:2:1: note: FIX-IT applied suggested code changes
^
/.../main.cpp:17:7: note: FIX-IT applied suggested code changes
    A(const Param& param) : m_param(param){}
      ^
/.../main.cpp:17:37: note: FIX-IT applied suggested code changes
    A(const Param& param) : m_param(param){}
                                    ^
/.../main.cpp:17:42: note: FIX-IT applied suggested code changes
    A(const Param& param) : m_param(param){}
                                         ^

并将代码修改为:

class A {
public:
    A(Param  param) : m_param(move(param)){}
    Param m_param;
};

如果我然后运行我得到的二进制文件:

constructor
copy constructor
move constructor
destructor
destructor
destructor

问题:

1 - 在这两种情况下都需要复制构造函数:

  • 复制到成员变量
  • 复制构造函数参数

但为什么clang-tidy“认为”额外移动构造函数实际上有帮助?这不仅会增加额外的计算成本吗?

http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html

文档说它假设移动很便宜(这很有意义),但是你不是要把它添加到副本中吗?

编辑:似乎这个问题得到了回答here。我对问题2仍然很好奇。

2 - 假设我误解了某些东西并且铿锵有力是正确的,那么在进行子类化时应该怎么做?两次传递值?

class A {
public:
    A(Param  param) : m_param(move(param)){}
    Param m_param;
};

class B : public A {
public:
    B(Param param) : A(move(param)){}
};

0 个答案:

没有答案