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

标签 c++ c++11 move-semantics rvalue-reference move-constructor

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

我的目标是只使用一对中的一个(例如,只使用接受右值的),以及其他的。我看了std::forward的引用资料,据我了解,好像就是为了这个目的。但是,当我删除左值引用时,出现以下编译器错误。

'TestClass::TestClass(const TestClass &)': cannot convert argument 1 from 'std::wstring' to 'std::wstring &&'

如何防止此代码重复?

#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 . . .

最佳答案

如果 move 构造预计会非常便宜,您可以按值取值并从值中 move 。这比一对复制和 move 重载正好多了 1 个 move 。

如果您想要最佳效率,和/或如果 move 构造便宜但又不是便宜到可以忽略的程度,您可以转发:

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 使用按值(因为我们知道 move 成本低)并为 TestClass< 做转发的东西 代码(或任何不太可能稳定的代码)。

关于c++ - 如何防止右值和左值成员函数之间的代码重复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34160390/

相关文章:

c++ - Visual Studio Code : C++ include path

c++ - 使用 move 语义在构造函数中初始化类成员

c++ - C++11中auto是如何实现的

c++ - 如何防止 C++ 或 native 编译代码中的 I/O 访问

c++ - unique_ptr所有权疯狂

c++ - 为什么 g++ 允许我将此 void 函数视为除此之外的任何东西?

C++ 在键上将两个映射相交,保留第一个映射的值

c++ - 默认的 Move 构造函数是否定义为 noexcept?

c++ - std::unique_ptr 取得所有权前的测试

c++ - 为什么 opencv 的 Mat::rows 和 Mat::cols 是有符号的而不是无符号的?