技术向 | C++函数形参怎么写效率最高? constT& OR T&&

1. 简介

  • 本文探讨了函数形参的三种写法
    • 方法一:const T& —— 最常见
    • 方法二:const T& + T&& + move
    • 方法三:T + move
  • 换句话说
    • 写代码的时候,经常会遇到,一个类的成员函数,需要从外部接收一个值,然后存到自己的成员变量里
    • 然后关于这个问题,C++里怎么写,效率最高(结合move语义)

2. 实验内容

  • 编译器:gcc.exe (x86_64-win32-seh-rev1, Built by MinGW-Builds project) 13.1.0

  • 编译命令:g++ main.cpp -std=c++17 -O3 && .\a.exe

  • 代码1:只实现了 const T&(最平凡的写法)

    #include <bits/stdc++.h>

    using uint = uint32_t;

    struct S {
    S() { std::cout << "\tS Default" << std::endl; }
    S(const S&) { std::cout << "\tS Copy" << std::endl; }
    S(S&&) { std::cout << "\tS Move" << std::endl; }
    };

    struct Node {
    Node(const S& t) : m_t(t) { std::cout << "Node Copy" << std::endl; }
    // Node(S&& t) : m_t(std::move(t)) { std::cout << "Node Move" << std::endl; }
    // Node(S t) : m_t(std::move(t)) { std::cout << "Move" << std::endl; }
    S m_t;
    };

    int main() {
    S t;
    std::cout << "Start" << std::endl;

    Node node1(t);
    Node node2(std::move(t));

    return 0;
    }

    /*
    输出为:
    S Default
    Start
    S Copy
    Node Copy
    S Copy
    Node Copy
    */
  • 代码2:同时实现了 const T&T&&

    #include <bits/stdc++.h>

    using uint = uint32_t;

    struct S {
    S() { std::cout << "\tS Default" << std::endl; }
    S(const S&) { std::cout << "\tS Copy" << std::endl; }
    S(S&&) { std::cout << "\tS Move" << std::endl; }
    };

    struct Node {
    Node(const S& t) : m_t(t) { std::cout << "Node Copy" << std::endl; }
    Node(S&& t) : m_t(std::move(t)) { std::cout << "Node Move" << std::endl; }
    // Node(S t) : m_t(std::move(t)) { std::cout << "Move" << std::endl; }
    S m_t;
    };

    int main() {
    S t;
    std::cout << "Start" << std::endl;

    Node node1(t);
    Node node2(std::move(t));

    return 0;
    }

    /*
    输出为:
    S Default
    Start
    S Copy
    Node Copy
    S Move
    Node Move
    */
  • 代码3:实现了 T

    #include <bits/stdc++.h>

    using uint = uint32_t;

    struct S {
    S() { std::cout << "\tS Default" << std::endl; }
    S(const S&) { std::cout << "\tS Copy" << std::endl; }
    S(S&&) { std::cout << "\tS Move" << std::endl; }
    };

    struct Node {
    // Node(const S& t) : m_t(t) { std::cout << "Node Copy" << std::endl; }
    // Node(S&& t) : m_t(std::move(t)) { std::cout << "Node Move" << std::endl; }
    Node(S t) : m_t(std::move(t)) { std::cout << "Move" << std::endl; }
    S m_t;
    };

    int main() {
    S t;
    std::cout << "Start" << std::endl;

    Node node1(t);
    Node node2(std::move(t));

    return 0;
    }

    /*
    输出为:
    S Default
    Start
    S Copy
    S Move
    Move
    S Move
    S Move
    Move
    */

3. 实验结果

  • 总结

    • 编号 内容 实参左值 实参右值
      1 只实现了 const T& Copy Copy
      2 同时实现了 const T&T&& Copy Move
      3 实现了 T Copy + Move Move + Move
    • 所以,为了极致的性能,应该同时实现 const T&T&&

4. 参考