为什么这个构造函数是按原样编写的
Why is this constructor written as it is?
我们的教授在网上发布了一个自定义的"字符串"模板文件,并在不久前要求我们填写下面的函数。为了尝试理解这一点,我的问题是,为什么前三个构造函数都有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
的赋值。
- (SFML)按下键时,播放器构造函数未使用正确的动画进行更新
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 在按值调用 (c++) 中转发构造函数参数
- 构造函数中没有参数的对象类成员按什么顺序初始化?
- shared_ptr构造函数参数是否应按值传递
- 复制构造函数、按值传递和按值返回、链式操作、编译器
- 位集构造函数中的一元按位或折叠
- 如果函数按值传递并按值返回,将调用复制构造函数多少次
- 按值将对象传递给 SubClass 构造函数,导致超类的构造函数不调用
- 构造函数的初始值设定项列表中的函数调用是否按顺序排序?
- 多态性是否适用于值?或者在按(基)值返回时使用派生类的移动构造函数
- 引用成员到构造函数参数按值传递
- 构造函数未按预期工作
- 在C++11中按值返回构造的对象时,避免复制构造函数调用
- 移动构造函数未按预期调用
- 从按值构造函数参数初始化的引用成员
- C 构造函数按值
- 构造函数效率低下,适用于按值从函数返回对象的情况
- 移动构造函数未按预期调用
- 为什么这个构造函数是按原样编写的