c++ -调用存在对象的构造函数

C++ - calling to constructor on exist object

本文关键字:构造函数 对象 存在 调用 c++      更新时间:2023-10-16

我看到一些在c++上重构Object的代码。from GeeksForGeeks:

#include<iostream>
#include<string.h>
using namespace std;
class String
{
    char *p;
    int len;
public:
    String(const char *a);
};
String::String(const char *a)
{
    int length = strlen(a);
    p = new char[length +1];
    strcpy(p, a);
    cout << "Constructor Called " << endl;
}
int main()
{
    String s1("Geeks");  // line 1
    const char *name = "forGeeks";
    s1 = name; // line 3
    return 0;
}

现在,在第3行之后s1是一个不同的对象?

你看到的是一个赋值。

复制赋值操作符是在类中自动生成的,因为您自己没有定义。从我链接到的页面:

如果没有为类提供用户定义的复制赋值操作符类型(结构、类或联合),编译器总是会声明一个作为类的内联公共成员。

第3行实际上没有解引用:只是用另一个对象替换一个对象。第3行调用String的构造函数并将对象赋值给s1。所以创建了两个不同的String实例,但是构造函数没有在第一个对象上被"召回",而是将创建的实例赋值给s1。操作符=被用作其默认行为,即查找是否存在与给定为=操作符的类型匹配的构造函数。

另一方面,动态内存在代码中的任何点都没有被释放,这使得它成为一个糟糕的代码示例。

让我们来分析一下。

s1 = name;

首先,编译器将使用构造函数String(char const*)构造一个新的String对象。然后使用拷贝赋值操作符用这个新创建的对象更新s1

因为你没有定义这个操作符,它只是做一个类成员的副本,即plen:这是编译器为你生成的默认实现。旧对象之前没有清理,所以您正在泄漏内存…因此,您应该使用复制和交换习语编写复制语义:

class String {
    char *p;
    int len;
public:
    // Your constructors...
    // Swap function
    friend void swap(String& s1, String& s2) {
        using std::swap;
        swap(s1.p, s2.p);
        swap(s1.len, s2.len);
    }
    String(String const& other) : p(new char[other.len]()), len(other.len) {
        std::copy(other.p, other.p + len, p);
    }
    String& operator=(String other) {
        swap(*this, other);
        return *this;
    }
    // And finally, a destructor:
    /* virtual */ ~String() {
        delete [] p;
    }
};