Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.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++_Constructor_Compilation_Copy - Fatal编程技术网

C++复制构造函数不调用(编译错误)

C++复制构造函数不调用(编译错误),c++,constructor,compilation,copy,C++,Constructor,Compilation,Copy,这段代码没有编译请忽略运算符+中的值传递,我可以用引用替换它&但它仍然不能解决问题 我希望在主要功能方面: String s3 = s + s2; // COMPILATION ERROR 要编译是可以的,因为我声明了复制构造函数,但它没有给出匹配的构造函数 #include <iostream> #include <string> class String { public: String() { std::cout <<

这段代码没有编译请忽略运算符+中的值传递,我可以用引用替换它&但它仍然不能解决问题 我希望在主要功能方面:

String s3 = s + s2; // COMPILATION ERROR
要编译是可以的,因为我声明了复制构造函数,但它没有给出匹配的构造函数

#include <iostream>
#include <string>


class String {
public:
    String()
    {
        std::cout << "Constructor " << this << std::endl;
        data = new char[100];
    };

    String(char * str) : String()
    {
        std::cout << "Char * Constructor " << this << std::endl;
        strcpy(this->data,str);
    };

    String(String & rhs) : String() {
        std::cout << "Copy Constructor " << this << std::endl;
        strcpy(data, rhs.data);

    };


    void print() {
        printf("%s\n",data);
    }

    ~String() {
        std::cout << "Destructor " << this << std::endl;

        if (data) {
            delete data;
            data = nullptr;
        }
    };
    friend String operator+(String s1, String s2);

private:
    char * data;
};

String operator+(String s1, String s2)
{
    String temp;
    delete [] temp.data;
    temp.data =
    new char[strlen(s1.data) + strlen(s2.data) + 1];
    strcpy(temp.data, s1.data);
    strcat(temp.data, s2.data);
    return temp;
}


int main(int argc, const char * argv[])
{
    String s("herer");
    s.print();
    String s2 = s;
    s2.print();
    String s3 = s + s2; // COMPILATION ERROR
    return 0;
}
String(String & rhs)

复制构造函数的参数必须是const&


您的代码有几个错误。首先

String(char * str)
需要

String(const char * str)
如果要像在main中一样使用字符串文本,请使用string sherr;。其次,复制构造函数

#include <iostream>
#include <string>


class String {
public:
    String()
    {
        std::cout << "Constructor " << this << std::endl;
        data = new char[100];
    };

    String(char * str) : String()
    {
        std::cout << "Char * Constructor " << this << std::endl;
        strcpy(this->data,str);
    };

    String(String & rhs) : String() {
        std::cout << "Copy Constructor " << this << std::endl;
        strcpy(data, rhs.data);

    };


    void print() {
        printf("%s\n",data);
    }

    ~String() {
        std::cout << "Destructor " << this << std::endl;

        if (data) {
            delete data;
            data = nullptr;
        }
    };
    friend String operator+(String s1, String s2);

private:
    char * data;
};

String operator+(String s1, String s2)
{
    String temp;
    delete [] temp.data;
    temp.data =
    new char[strlen(s1.data) + strlen(s2.data) + 1];
    strcpy(temp.data, s1.data);
    strcat(temp.data, s2.data);
    return temp;
}


int main(int argc, const char * argv[])
{
    String s("herer");
    s.print();
    String s2 = s;
    s2.print();
    String s3 = s + s2; // COMPILATION ERROR
    return 0;
}
String(String & rhs)
需要采取行动

String(const String & rhs) 
这样它就可以绑定到临时对象

第三,为了使用strcpy,您需要包含或

最后,您在析构函数中使用了错误的delete。调用new时使用delete,使用new[]时调用delete[]。您使用new[]分配数据,但使用delete删除数据


您可以看到代码的工作示例

如果输入字符串包含100个以上的字符,会发生什么?通过常量引用将字符串传递给运算符以避免复制。不要删除字符串对象外部的内部数据,就像在运算符中一样。这违背了C++的优点。在external friend operator+中,如何更好地组织代码以不访问内部数据?字符串构造函数应该找出输入字符串的大小并分配正确的内存量。您还应该实现一个赋值运算符。感谢详细的代码审阅。现在更清楚了。因此编译器不允许非常量参数绑定到临时对象。顺便问一下,为什么它允许我在operator+中使用这个非常量复制构造函数呢?我的意思是,即使我使用reference&形式的itA reference也不能绑定到右值,这就是s+s2的结果。引用只能绑定到获取其名称的左值,因为它可以位于=符号的左侧。这就是为什么你可以在操作符+中复制它们,但是你不能复制它的结果,因为返回的字符串不是左值。哦,现在我明白了。这是有道理的。如果我使用带有地址的左值对象,编译器将使用复制构造函数的非常量引用形式。但是临时的s+s2表达式是右值,所以编译器不能用非常量引用绑定到它!我只能假设它是由于右值结果,所以无论如何都会被浪费掉,所以不需要使它可变,这就是为什么Compiler显式要求const ness的原因,非常感谢。这是有洞察力的:@巴尼,如果这个或任何答案已经解决了你的问题,请考虑通过点击复选标记。这向更广泛的社区表明,你已经找到了一个解决方案,并给回答者和你自己带来了一些声誉。没有义务这么做,还有更多的话要说。不幸的是,编译器不够智能,无法以更明确的方式指出这种类型转换问题。我必须有一些外部知识才能理解这个问题。只是到处有C++的高级编译器或静态分析器能立即显示问题吗?