使用移动和复制构造函数在 类 中复制 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
}
};
这种方法的开销是额外的移动构造函数。
不过不用担心,因为编译器可能会对其进行优化。
例如,具有两个构造函数的 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
}
};
这种方法的开销是额外的移动构造函数。 不过不用担心,因为编译器可能会对其进行优化。