如何防止右值和左值成员函数之间的代码重复

How do I prevent code repeat between rvalue and lvalue member functions?

本文关键字:之间 代码 函数 成员 何防止      更新时间:2023-10-16

对于下面的程序代码,我必须在接收右值和左值引用的一对成员函数中编写相同的代码。

我的目标是只使用这对中的一个(例如,只使用接受一个的右值),其他的。我阅读了std::forward的参考资料,据我所知,它似乎是为了这个目的。但是,当我删除使用1的左值引用时,我会得到以下编译器错误。

"TestClass::TestClass(const TestClass&)":无法将参数1从"std::wstring"转换为"std:&'

如何防止这种代码重复?

#include <iostream>
#include <string>
class TestClass
{
    public:
        TestClass(const std::wstring    &  Text)
            : Text(Text)
        {
            std::wcout << L"LValue Constructor : " << Text << std::endl;
            /*Some code here...*/
        }
        TestClass(      std::wstring    && Text)
            : Text(std::forward<std::wstring>(Text))
        {
            std::wcout << L"RValue Constructor : " << this->Text << std::endl;
            /*Same code here...*/
        }
        TestClass(const TestClass       &  Another)
            : Text(Another.Text)
        {
            std::wcout << L"Copy   Constructor : " << Text << std::endl;
            /*Some code here...*/
        }
        TestClass(      TestClass       && Another)
            : Text(std::forward<std::wstring>(Another.Text))
        {
            std::wcout << L"Move   Constructor : " << Text << std::endl;
            /*Same code here...*/
        }
    private:
        std::wstring Text;
};
int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
    std::wstring Argument(L"Testing Copy");
    TestClass Class1Copy(Argument);
    TestClass Class1Move(L"Testing Move");
    TestClass Class2Copy(Class1Copy);
    TestClass Class2Move(std::move(Class1Move));
    _wsystem(L"pause");
    return 0;
}

输出:

LValue Constructor : Testing Copy  
RValue Constructor : Testing Move  
Copy   Constructor : Testing Copy  
Move   Constructor : Testing Move  
Press any key to continue . . .

如果移动构建预计非常便宜,那么您可以按价值进行移动。这正好比一对复制和移动重载多移动一次。

如果你想要最佳效率,和/或如果移动结构更便宜,但便宜

template<class T>
std::decay_t<T> copy(T&& t) {
  return std::forward<T>(t);
}
class TestClass {
public:
  TestClass(std::wstring const&  Text)
    TestClass( copy(Text) )
  {}
  TestClass(TestClass const& o)
    : TestClass( o.Text )
  {}
  TestClass(TestClass&& o)
    : TestClass( std::move(o).Text ) // pattern does the right thing more often than `std::move(o.Text)` does.
  {}
  // only "real" ctor:
  TestClass( std::wstring&& Text)
    : Text(std::forward<std::wstring>(Text))
  {
    std::wcout << L"RValue Constructor : " << this->Text << std::endl;
    /*Code here...*/
  }
// ...

现在所有的事情都转到一个构造函数。

您甚至可以混合使用这两种技术:按值使用std::wstring(正如我们所知,移动起来很便宜)和为TestClass代码做转发(或者任何不太可能稳定的代码)。

您可以按值,然后按move。那么您只需要N过载,而不需要2N:

TestClass(std::wstring Text)
    : Text(std::move(Text))
{
}

你可以通过什么都不写来避免复制构造函数和移动构造函数的重复;在这种情况下,编译器将默认生成它们。

我认为您无法做到这一点,因为函数的签名决定了何时何地使用它们。它就像一个copy constructor和一个assignment operator。它们做了一些类似的事情,但编译器会根据上下文调用相应的。

如果您想避免重复使用代码,只需将通用性考虑到一个单独的函数中即可。

相关文章: