c++ - 使用右值编写 operator+ 的正确方法

标签 c++ visual-c++

我一直在编写自己的 String 类,考虑到我可以将右值传递给它,我不确定如何正确编写 operator+。我认为我应该具有以下 3 个非成员函数

String operator+(String &&lhs, String &&rhs);
String operator+(String& lhs,String&&rhs);
String operator+(String&&lhs,String&rhs);

但是我不确定如何实现它们。任何帮助将不胜感激。

最佳答案

首先,确保在 String 中定义复制和移动构造函数类:

class String
{
private:
    char *m_data;
    std::size_t m_length;
    ...

public:
    String();
    String(const String &src);
    String(String &&src);
    ~String();
    ...
};

String::String() :
    m_data(nullptr),
    m_length(0)
{
}

String(const String &src) :
    m_data(new char[src.m_length+1]),
    m_length(src.m_length)
{
    std::copy_n(src.m_data, m_length, m_data);
    m_data[m_length] = 0;
}

String(String &&src) :
    m_data(nullptr),
    m_length(0)
{
    std::swap(m_data, src.m_data);
    std::swap(m_length, src.m_length);
}

String::~String()
{
    delete[] m_data;
}

然后定义operator+operator+=对于类(class):

class String
{
public:
    ...
    String& operator+=(const String &rhs);
    ...
    friend String operator+(String lhs, const String &rhs)
    {
        lhs += rhs;
        return lhs;
    }
};

String& String::operator+=(const String &rhs)
{
    String tmp;
    tmp.m_length = m_length + rhs.m_length;
    tmp.m_data = new char[tmp.m_length+1];
    std:copy_n(m_data, m_length, tmp.m_data);
    std:copy_n(rhs.m_data, rhs.m_length, tmp.m_data + m_length);
    tmp.m_data[tmp.m_length] = 0;
    std::swap(m_data, tmp.m_data);
    std::swap(m_length, tmp.m_length);
    return *this;
}

通过 const String &作为右侧的输入,它将处理左值和右值输入。

对于 operator+ ,左侧按值取值,因此编译器可以根据输入是左值(复制)还是右值(移动)来决定要使用的最佳构造函数。

或者,您可以实现它以获取 const String &在左侧,所以它仍然处理左值和右值,但是你必须像operator+=那样实现它实现是为了避免复制的额外分配lhs在连接到它之前:

friend String operator+(const String &lhs, const String &rhs)
{
    /*
    String tmp(lhs);
    tmp += rhs;
    return tmp;
    */

    String tmp;
    tmp.m_length = lhs.m_length + rhs.m_length;
    tmp.m_data = new char[tmp.m_length+1];
    std:copy_n(lhs.m_data, lhs.m_length, tmp.m_data);
    std:copy_n(rhs.m_data, rhs.m_length, tmp.m_data + lhs.m_length);
    tmp.m_data[tmp.m_length] = 0;
    return tmp;
}

无论哪种方式,您还应该定义一个转换构造函数和operator+对于 const char *也输入:

class String
{
public:
    ...
    String(const char *src);
    ...
    friend String operator+(const char *lhs, const String &rhs)
    {
        return String(lhs) + rhs;

        /* or:

        std::size_t len = std::strlen(lhs);
        String tmp;
        tmp.m_length = len + rhs.m_length;
        tmp.m_data = new char[tmp.m_length+1];
        std:copy_n(lhs, len, tmp.m_data);
        std:copy_n(rhs.m_data, rhs.m_length, tmp.m_data + len);
        tmp.m_data[tmp.m_length] = 0;
        return tmp;
        */
    }
    ...
};

String::String(const char *src) :
    m_data(nullptr),
    m_length(std::strlen(src))
{
    m_data = new char[m_length+1];
    std::copy_n(src, m_length, m_data);
    m_data[m_length] = 0;
}

这将允许连接 String具有字符串文字的对象( String + "literal""literal" + StringString += "literal" 等)。

参见 operator overloadingcppreference.com了解更多详情。

关于c++ - 使用右值编写 operator+ 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46834880/

相关文章:

c++ - 在将 constexpr 添加到语言后,将变量声明为 const 是多余的吗?

c++ - 如何unordered_set<tuple<int,int>>?

winapi - 获取完整的运行过程列表(Visual C++)

visual-studio - 存储新类的默认目录?

c - 为什么 floor() 这么慢?

python - C1083 无法打开包含文件 : "Python.h": No such file or directory

c++ - 从 std::stoi 获取基数

c++ - 在cpp中查找二维字符串数组长度的函数?

c++ - 我应该怎么做而不是函数模板的部分特化?

c++ - Win32 C++ : Creation and Calling method from separate C++ file