【问题标题】:Copy Constructor Undefined Call复制构造函数未定义调用
【发布时间】:2015-06-11 12:03:14
【问题描述】:

这是完整的示例(源书:C++ From Ground Up,第 3 版,第 219-320 页):

class sample {
    char *s;
    public:
        sample(); // normal constructor
        sample(const sample &ob); // copy constructor
        ~sample( ) { cout << "s: " << s <<" ,Freeing s\n"; if(s) delete [] s;}
        void show() { cout << s << "\n"; }
        void set(char *str);
        sample operator=(const sample &ob); // overload assignment
};
// Normal constructor.
sample::sample() {
    s = new char('\0'); // s points to a null string.
    cout << "Normal constructor: s: " << strlen(s) << endl;
}
// Copy constructor.
sample::sample(const sample &ob) {
    cout << "Copy constructor: ob.s: "<< ob.s << " ,strlen(ob.s): " <<  strlen(ob.s) << "\n";
    s = new char[strlen(ob.s)+1];
    strcpy(s, ob.s);
}
// Load a string.
void sample::set(char *str) {
    s = new char[strlen(str)+1];
    strcpy(s, str);
}
// Overload assignment operator.
sample sample::operator=(const sample &ob) {
    /* If the target memory is not large enough
    then allocate new memory. */
    cout << "operator= strlen(ob.s): " << strlen(ob.s) << " ,strlen(s): " << strlen(s) << endl;

    if(strlen(ob.s) > strlen(s)) {
        cout << "operator= Larger memory of target object. Deleting current...\n";
        delete [] s;
        s = new char[strlen(ob.s)+1];
    }
    strcpy(s, ob.s);

    return *this;
}
// Return an object of type sample.
sample input() {
    char instr[80];
    static sample str;
    cout << "Enter a string: ";
    cin >> instr;
    str.set(instr);

    return str;
}

int main() {
    sample ob;
    // assign returned object to ob
    ob=input(); // This is now OK
    ob.show();

    return 0;
}

但是我不明白为什么调用了 TWO 次复制构造函数。 (运行代码后输出)

Normal constructor: s: 
Normal constructor: s: 
Enter a string: Hello
Copy constructor: ob.s: Hello ,strlen(ob.s): 5
operator= strlen(ob.s): 5 strlen(s): 0
operator= Larger memory of target object. Deleting current...
Copy constructor: ob.s: Hello ,strlen(ob.s): 5 
s: Hello, Freeing s
s: Hello, Freeing s
Hello
s: Hello, Freeing s
s: Hello, Freeing s

我知道它在 input() 函数返回时被调用,并创建临时对象(通过调用复制构造函数),但我不明白为什么第二次,据我所知(但也许我错了)复制构造函数被 NOT 调用以进行赋值操作,但看起来,尽管如此,当 return *this; 被调用时(当重载运算符返回值时),复制构造函数被调用了吗? 我错过了什么?

谢谢

【问题讨论】:

  • 这整个new/delete 业务并不是最佳实践。您可能想投资better book
  • 这真的是一本书的样本吗?这是非常糟糕的代码。无缘无故使用静态变量,如果set被调用两次内存泄漏,newdelete[]不匹配,手动内存管理等。
  • 这是一本“Schild”书(而且是雪上加霜——旧版),只要有见识的人看着它们,它们就会获得最低的评论分数。正如@BaummitAugen 建议的那样,买一本更好的书!
  • 实际上 static 是我自己错误输入的(但这是另外一个复制构造函数调用的原因)。但是,原始示例甚至不会编译,因为它在重载赋值声明/定义中没有 const。只有当我添加这个关键字时它才想编译。

标签: c++ copy-constructor


【解决方案1】:

代码真的很糟糕。更不用说其他错误了,这就是为什么复制构造函数被调用两次的原因。

  1. 第一次从input()返回对象时调用它,因为它是静态的,按值返回,所以不能应用RVO。

  2. 第二次调用是由于operator=() 中的return *this; 而发生的,因为出于某种原因它也按值返回了一个对象:

    sample operator=(const sample &ob);
    // ^^^
    

【讨论】:

  • 您好,感谢您的观察。正如我在之前的评论中所描述的,静态是我不小心添加的,但是示例甚至不想使用书中的原始代码进行编译。但是,我认为“复制构造函数仅适用于初始化,它不适用于赋值”(至少在我阅读的书中也写过,而且我在 stackoverflow 中发现很少确认该声明)。那么实际上这是错误的吗?即使运算符重载函数返回相同类型的对象,也会调用复制构造函数?
  • @Creator 如果一个完整的代码示例不能在现代编译器中运行,那么是时候通读这本书了。学习坏事对你没有好处。有一些非常好的书here,你应该看看使用而不是你拥有的。
猜你喜欢
  • 1970-01-01
  • 2012-02-28
  • 2012-02-06
  • 1970-01-01
  • 2018-11-29
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多