代码之家  ›  专栏  ›  技术社区  ›  Amit G.

在构造函数中初始化字符串成员的首选方法是什么?

  •  3
  • Amit G.  · 技术社区  · 6 年前

    下面是一个具有一个字符串成员的类。我们希望在构造函数中对其进行初始化:

    class MyStr {
        std::string m_str;
    
    public:
        MyStr(const std::string& rstr) : m_str(rstr) {}
    };
    

    构造函数采用conSTD::

    我们可以用字符串视图替换常量引用:

    MyStr(std::string_view strv) : m_str(strv) {}
    

    或按值传递字符串并从中移动:

    MyStr(std::string str) : m_str(std::move(str)) {}
    

    首选哪种方案?

    3例:

    MyStr mystro1{"Case 1: From a string literal"};
    
    std::string str2 { "Case 2: From l-value"};
    MyStr mystro2 { str2 };
    
    std::string str3 { "Case 3: From r-value reference"};
    MyStr mystro3 { std::move(str3) };
    
    4 回复  |  直到 6 年前
        1
  •  2
  •   Maxim Egorushkin    6 年前

    最有效的方法是将任何可转换为 std::string :

    class MyStr {
        std::string m_str;
    
    public:
        template<class T,
                 class = std::enable_if_t<std::is_convertible<std::remove_reference_t<T>, std::string>::value>>
        MyStr(T&& arg)
            : m_str(std::forward<T>(arg))
        {}
    };
    

    不过,有一点点。第二个最好的选择是根本不提供构造函数,将数据成员公开并初始化 MyStr 使用聚合初始化语法。

    完整故事: CppCon 2017: Nicolai Josuttis “The Nightmare of Move Semantics for Trivial Classes” .

        2
  •  1
  •   Julius    6 年前

    这是一个 实用经验法则 更一般的范围是:

    全部通过 廉价可移动 阿西 按值接收参数并使用 std::move 在适当的时候。

    阿西 以下类型的主要示例: 廉价可移动 : std::array 和其他类型 T 哪里 sizeof(T) 是“大”

    这通常是可用性(在接口的任一侧)和计算开销之间的一个很好的折衷。通常,额外的工作(与完美的转发相比)最多是一个额外的移动结构,最多是一个额外的解构。除非您已经确定了应用程序的性能瓶颈,否则您很可能不想花费更多的编程工作。

    This blog post on how to pass sink arguments 包括对备选方案的较长讨论,其结论还以“坚持按值传递”作为默认值开始。

    应用于您的 std::string 成员示例 这表明

    class MyStr {
        std::string m_str;
    
    public:
        MyStr(std::string rstr) : m_str(std::move(rstr)) {}
    };
    

    除了上述一般性能方面外,请注意签名 MyStr::MyStr(std::string rstr) 意味着 MyStr 正在存储 事情 作为 rstr . 这可能有助于用户了解 迈斯特 应该使用。

        3
  •  0
  •   cpp_enthusiast    6 年前

    正如Clonk所说,您需要具体说明您想要什么。你在找表演还是别的什么?

    此外,您还可以使用编译器资源管理器自己对其进行比较。

    https://godbolt.org/ .

    在编译器资源管理器中编写代码,它将自动生成汇编代码。当然,您可以选择编译器。

        4
  •  0
  •   Amit G.    6 年前

    完整答案: Analysing the Cases