Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 写入运算符+;使用右值_C++_Visual C++ - Fatal编程技术网

C++ 写入运算符+;使用右值

C++ 写入运算符+;使用右值,c++,visual-c++,C++,Visual C++,我一直在编写自己的字符串类,考虑到我可以将右值传递给它,我不确定如何正确编写运算符+ String operator+(String &&lhs, String &&rhs); String operator+(String& lhs,String&&rhs); String operator+(String&&lhs,String&rhs); 然而,我不知道如何实施它们。任何帮助都将不胜感激。首先,请确保在字符串

我一直在编写自己的字符串类,考虑到我可以将右值传递给它,我不确定如何正确编写运算符+

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

然而,我不知道如何实施它们。任何帮助都将不胜感激。

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

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

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

然后为类定义
operator+
operator+=

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

通过将
常量字符串&
作为右侧的输入,它将处理左值和右值输入

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

或者,您可以将其实现为在左侧使用
常量字符串&
,这样它仍然可以处理左值和右值,但是您必须实现它,就像
操作符+=
实现一样,以避免在连接到它之前复制
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;
}
无论哪种方式,您还应该为
const char*
输入定义转换构造函数和
operator+

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+“literal”
“literal”+String
String+=“literal”
等)连接起来


有关更多详细信息,请参见上。

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

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

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

然后为类定义
operator+
operator+=

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

通过将
常量字符串&
作为右侧的输入,它将处理左值和右值输入

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

或者,您可以将其实现为在左侧使用
常量字符串&
,这样它仍然可以处理左值和右值,但是您必须实现它,就像
操作符+=
实现一样,以避免在连接到它之前复制
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;
}
无论哪种方式,您还应该为
const char*
输入定义转换构造函数和
operator+

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+“literal”
“literal”+String
String+=“literal”
等)连接起来


有关详细信息,请参见上。

我通常这样做:

class foo
{
...
public:
...
  foo&& operator +(foo const & other) &&;
  foo&& operator +(foo && other) const &;
  foo&& operator +(foo && other) &&;
  foo   operator +(foo const & other) const &;
};
不确定Microsoft是否支持这一点,但在较新的标准中,这是一种很好的方法。如果msvc不允许,试试叮当声

这样做的好处是,您可以对所使用的方法进行非常精细的控制。如果需要,还可以在类外定义这4个操作。但对于r值/l值组合的4种可能性,您总是需要4

此外,您通常希望将l值限定为常量,以指示它们未被修改


简单地定义复制/移动构造函数通常不是解决此问题的有效方法。您需要很好地了解右值引用如何有效地实现此功能。

我通常这样做:

class foo
{
...
public:
...
  foo&& operator +(foo const & other) &&;
  foo&& operator +(foo && other) const &;
  foo&& operator +(foo && other) &&;
  foo   operator +(foo const & other) const &;
};
不确定Microsoft是否支持这一点,但在较新的标准中,这是一种很好的方法。如果msvc不允许,试试叮当声

这样做的好处是,您可以对所使用的方法进行非常精细的控制。如果需要,还可以在类外定义这4个操作。但对于r值/l值组合的4种可能性,您总是需要4

此外,您通常希望将l值限定为常量,以指示它们未被修改


简单地定义复制/移动构造函数通常不是解决此问题的有效方法。您需要很好地理解右值引用如何有效地实现这一点。

您肯定缺少标准重载
const-String&,const-String&
。您可以找到一些指导和示例。数百万人在编写自己的字符串类之前,从未制作过比标准字符串类功能更好或bug更少的字符串类。所以,除非这只是一个学术练习,否则就放弃这个目标吧@ChristopherPisz如果
std::string
的作者有这样一个attidute,那么我们就只有最糟糕的实现了。看到右值的好处是你知道它是一个临时值,并且可以自由地将它搞砸(确保析构函数仍然工作)。例如,在第三个重载中,可以执行
lhs+=rhs;返回标准::移动(lhs)
lhs
窃取资源,避免你自己的资源,但既然
lhs
马上就死了,那没关系。@Rostislavstoyanov好吧,这是一个学术背景。我同情你。不使用STL的地方创建我必须使用的不使用STL的程序员:/您肯定缺少标准重载
const-String&,const-String&
。您可以找到一些指导和示例。数百万人在编写自己的字符串类之前,从未制作过比标准字符串类功能更好或bug更少的字符串类。所以,除非这只是一个学术练习,否则就放弃这个目标吧@ChristopherPisz如果
std::string
的作者有这样一个attidute,那么我们就只有最糟糕的实现了。看到右值的好处是你知道它是一个临时值,并且可以自由地将它搞砸(确保析构函数仍然工作)。例如,在第三个重载中,可以执行
lhs+=rhs;返回标准::移动(lhs)从中窃取资源