//头文件中:类定义:
class myString
{
public:
myString(void);
myString(const char *str);
myString(const myString &); //copy constructor
~myString(void); //destructor
void swap(myString &from);
private:
char *stringPtr;
int stringLen;
};//在cpp文件中,定义其成员函数
myString::myString(const char *str)
{
stringLen = strlen(str);
stringPtr = new char[stringLen+1];
strcpy(stringPtr,str);
cout << "constructor with parameter called"<<endl;
}
myString::myString(const myString &str)
{
stringPtr = new char[str.stringLen +1];
strcpy(stringPtr,str.stringPtr);
cout << "copyconstructor"<<endl;
}
void myString::swap(myString &from)
{
myString buffer(from);
int lengthBuffer = from.stringLen;
from = new char[stringLen+1];
from.stringLen = stringLen;
strcpy(from.stringPtr, stringPtr);
stringPtr = new char[lengthBuffer+1];
stringLen = lengthBuffer;
strcpy(stringPtr,buffer.stringPtr);
}发布于 2009-10-22 14:17:27
您不能修改引用。即使您将其替换为指针,修改指针也不会修改指向的对象。相反,您需要完成引用--只需交换字段即可。
void myString::swap(myString &from)
{
std::swap( stringLen, from.stringLen );
std::swap( stringPtr, from.stringPtr );
}上面使用的是user sbi在注释中建议的std::swap()。这完全等同于下面(只是为了说明,不要重新发明STL):
void myString::swap(myString &from)
// First remember own length and pointer
const int myOldLen = stringLen;
char* myOldPtr = stringPtr;
// now copy the length and pointer from that other string
stringLen = from.stringLen;
stringPtr = from.stringPtr;
// copy remembered length and pointer to that other string
from.StringLen = myOldLen;
from.StringPtr = myOldPtr;
// done swapping
}即使在调用自交换时,这两种方法也可以正常工作:
myString string;
string.swap( string );发布于 2009-10-22 15:32:02
关于myString::swap()函数中的错误,您已经得到了一些很好的答案。然而,我想添加另一个。这个函数有很多错误,我一开始发现很难考虑从哪里开始。但后来我意识到你在一些基本问题上失败了,我想指出的是:
通常,需要一个名为swap的函数来执行其任务
O(1)
(是的,我知道,也有例外:std::tr1::array<>::swap()。但这些都应该是非常合理的。)您的实现在两个帐户上都失败了。它是O(n) (strcpy),并且可能抛出一个异常(new) --它这样做是不必要的,而且没有正当理由。
当您查看myString时,您将看到它只有两部分成员数据,这两部分都是内置类型。这意味着交换这个类的两个对象非常简单,同时遵循上面提到的约定:只交换成员数据。这就像对它们调用std::swap一样简单:
void myString::swap(myString &from)
{
std::swap(this->stringPtr,from.stringPtr);
std::swap(this->stringLen,from.stringLen);
}这是永远不会失败的(交换两个指针和两个整数不会失败),用O(1)执行,非常容易理解(好吧,一旦您掌握了这种交换,不管怎样,它是实现特定于类的swap函数的惯用形式),它由两行代码调用标准库中经过良好测试的东西组成,而不是由8行代码进行容易出错(在您的例子中是错误的)的手动内存管理。
注意1:一旦你这样做了,你应该指定std::swap来调用你的类的实现:
namespace std { // only allowed for specializing function templates in the std lib
template<>
inline void std::swap<myString>(myString& lhs, myString& rhs)
{
lhs.swap(rhs);
}注2:实现类赋值的最好方法(简单、异常安全和自赋值安全)是使用它的swap:
myString& myString::operator=(const myString& rhs)
{
myString tmp(rhs); // invoke copy ctor
this->swap(tmp); // steal data from temp and leave it with our own old data
return *this;
} // tmp will automatically be destroyed and takes our old data with it发布于 2009-10-22 14:21:19
from = new char[stringLen+1];应为from.stringPtr = new char[stringLen+1];。另外,记得在分配新内存之前释放以前分配的内存。
https://stackoverflow.com/questions/1605312
复制相似问题