为什么这个构造函数是按原样编写的

Why is this constructor written as it is?

本文关键字:按原样 构造函数 为什么      更新时间:2023-10-16

我们的教授在网上发布了一个自定义的"字符串"模板文件,并在不久前要求我们填写下面的函数。为了尝试理解这一点,我的问题是,为什么前三个构造函数都有Text = NULL;,在它下面有this = source;,还有其他形式。我觉得每个构造函数都应该说Text = the_input_parameter

非常感谢,这是代码:

class String
{
public:
    // Default constructor
    String()
    {
        Text = NULL;
    }
    String(const String& source)
    {
        Text = NULL;
        // Call the assignment operator to perform deep copy
        *this = source;     
    }
    String(const char* text)
    {
        Text = NULL;
        // Call the assignment operator to perform deep copy
        *this = text;
    }
~String()
    {
        delete[] Text;
    }
    // Assignment operator to perform deep copy
    String& operator = (const char* text)
    {
        // Ddispose of old Text
        delete[] Text;
        // +1 accounts for NULL-terminator
        int trueLength = GetLength(text) + 1;
        // Dynamically allocate characters on heap
        Text = new char[trueLength];
        // Copy all characters from source to Text; +1 accounts for NULL-terminator
        for ( int i = 0; i < trueLength; i++ )
            Text[i] = text[i];
        return *this;
    }
    // Returns a reference to a single character from this String
    char& operator [] (int index) const
    {
        int length = GetLength();
        // Check for valid index
        if ( (index < 0) || (index > length) )
        {
            stringstream error;
            error << "operator[] - index " << index << " is out of bounds (0.." << (length - 1) << ")";
            throw String(error.str().c_str());
        }
        return Text[index];
    }
private:
    // The encapsulated C-string
    char* Text;
};

为什么不应该在赋值方面实现构造函数:

  • 它在派生类中变得相当糟糕。想想看
  • 很难保证例外情况的安全
  • 它的启动效率也很低(需要默认构造,然后分配(

因此,为什么它的答案&rsquo的;在你的示例代码中是这样做的,可能是你的教授没有;我对C++编程一知半解。

否则,很难说:这样做根本没有任何意义。


然而,走另一条路,即在副本构造方面实现副本分配,这是非常常见的,被称为复制和交换习语

它很简单,异常安全,总体高效,如下所示:

class Foo
{
public:
    void swap_with( Foo& other ) throw()
    {
        // No-throwing swap here.
    }
    void operator=( Foo other )
    {
        other.swap_with( *this );
    }
};

是的,仅此而已。

变体包括仅将交换器命名为swap,并让赋值运算符返回一个引用,有些更喜欢通过引用传递参数,然后进行复制(使用复制构造(。

这只是将公共代码分解为辅助函数的一种方法。在这种情况下,operator=()充当辅助函数。它的功能是解除分配当前字符串(在本例中为NULL(并执行右侧的深度复制。

我觉得每个人都应该说Text = the_input_parameter

对于String(const String& source),这不会编译,因为source不是正确的类型。

对于String(const char* text),这是不正确的,因为这只会分配指针,而不是执行深度复制。

以上假设您只向我们展示了类的一部分,并且实际的类定义了一个适当的赋值运算符和一个析构函数。如果没有,你需要一个新教授。

类管理内存,因此析构函数释放内存,赋值运算符为新数据分配新数据并释放旧数据(应该按照这个顺序(。

然后,对初始赋值的解释很清楚:您需要将成员字段初始化为正确的值,否则它将包含垃圾(指向某个地方的指针(,代码将尝试使用并释放这些垃圾。

虽然从代码中看不出来,但可能还有const String&和类型转换运算符operator const char *() const的赋值。