使用移动和复制构造函数在 类 中复制 C++ 代码

C++ code duplication in classes with both move and copy constructors

例如,具有两个构造函数的 class,一个采用引用,另一个采用字符串右值引用。

class A {
    public:

    A(std::string&& str) {
        Foo foo(std::move(str));
        //do something with foo. (e.g., use it to initialize some members)
        field = foo.bar();
    }

    A(const std::string& str) {
        Foo foo(str);
        //do something with foo. (e.g., use it to initialize some members)
        field = foo.bar();
    }

};

如果这两个构造函数除了 std::move 出现在移动构造函数中之外几乎执行相同的操作,是否有任何方法可以避免有两个几乎相同的代码块?

显而易见的答案:制作第三个 fn,它执行公共部分,从其他两个 fns 调用。

您可以直接从另一个调用一个,但这取决于 class 中存储的数据的性质以及所引用的内容。但是,在许多情况下,如果需要,可以使用复制构造函数来实现移动,但效率不高。

您可以使用通用引用来执行此操作,但仅限于构造函数已模板化的情况。

class A {
public:
    template<typename T>
    A(T && str) {
        Foo foo(std::forward<T>(str));
        //do something
    }
};

按值接受。这将起到与两者相同的作用。

第一个选项是使用模板化构造函数:

class A
{
public:
    template<typename T, typename = std::enable_if<std::is_same<std::remove_reference<T>::type, std::string>::value>::type>
    A(T && str) {
         Foo foo(std::forward<T>(str));
        //do something
    }
};

不过有点难看。如果 Foo(const std::string &) 实际上复制了字符串,那么我更愿意按值传递参数:

class A
{
public:
    A(std::string str) {
         Foo foo(std::move(str));
        //do something
    }
};

这种方法的开销是额外的移动构造函数。 不过不用担心,因为编译器可能会对其进行优化。