Sad*_*que 11 c++ string operator-overloading visual-c++
在C++ Primer一书中,它有一个C风格字符数组的代码,并展示了如何=在第15.3条Operator =中重载运算符.
String& String::operator=( const char *sobj )
{
// sobj is the null pointer,
if ( ! sobj ) {
_size = 0;
delete[] _string;
_string = 0;
}
else {
_size = strlen( sobj );
delete[] _string;
_string = new char[ _size + 1 ];
strcpy( _string, sobj );
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
现在我想知道为什么String &在下面的代码执行相同的工作时需要返回引用,没有任何问题:
void String::operator=( const char *sobj )
{
// sobj is the null pointer,
if ( ! sobj ) {
_size = 0;
delete[] _string;
_string = 0;
}
else {
_size = strlen( sobj );
delete[] _string;
_string = new char[ _size + 1 ];
strcpy( _string, sobj );
}
}
Run Code Online (Sandbox Code Playgroud)
Fre*_*Foo 20
它支持以下习语:
String a, b;
const char *c;
// set c to something interesting
a = b = c;
Run Code Online (Sandbox Code Playgroud)
为此,b = c必须返回适当的对象或引用来分配a; 它实际上是a = (b = c)根据C++运算符优先级规则.
如果你要返回指针this,你必须写a = *(b = c),这不会传达预期的含义.
@larsmans已经回答了你的确切问题,所以我真的会离题:这是一些糟糕的代码!
这里的问题是3倍:
strcpy可以更好地替换strncpy,它做一些绑定检查1)和2)比任何东西都更具风格,但3)是一个大问题
编辑:正如@Jerry Coffin指出的那样,这并不能防止自我分配.那就是如果sobj并且_string指向相同的字符数组,那你就会遇到很大麻烦.本文末尾的简单解决方案也涵盖了这种情况.
也不例外
让我们看一下代码的else一部分,即部分:
_size = strlen( sobj );
delete[] _string;
_string = new char[ _size + 1 ];
strcpy( _string, sobj );
Run Code Online (Sandbox Code Playgroud)
如果出于某种原因new抛出什么会发生什么?
_size 具有新字符串的值_string 指向旧指针......已被释放因此,不仅对象处于不可用状态(其中一半数据来自新对象,一半来自旧对象),但它甚至无法销毁(除非析构函数泄漏......?)
添加异常安全,艰难的方式
_size = strlen( sobj );
delete[] _string;
try {
_string = new char[ _size + 1 ];
} catch(...) {
_size = 0; _string = 0;
throw;
}
strcpy( _string, sobj );
Run Code Online (Sandbox Code Playgroud)
好吧,它真的是底线,但它给我们带来了基本的异常保证:没有功能保证,但保证代码在技术上是正确的(没有崩溃,没有泄漏).
添加异常安全,简单方法:Copy-And-Swap成语
在以下位置查找更完整的说明:什么是复制和交换习惯用法?
void swap(String& lhs, String& rhs) {
using std::swap;
swap(lhs._size, rhs._size);
swap(lhs._string, rhs._string);
}
String& String::operator=(String other) { // pass-by-value
swap(*this, other);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
它是如何工作的 ?
它甚至比以前的版本更好,因为现在我们有强异常保证:它是事务性的,因此如果失败,我们分配给的字符串不变(好像什么也没发生).
我有点沮丧,C++教程会推广这些可疑的代码,请告诉我这是一个不该做的例子:/