首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未复制字符数组,函数交换无法正确编译,stringPtr未修改

未复制字符数组,函数交换无法正确编译,stringPtr未修改
EN

Stack Overflow用户
提问于 2009-10-22 14:13:39
回答 4查看 711关注 0票数 0

//头文件中:类定义:

代码语言:javascript
复制
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文件中,定义其成员函数

代码语言:javascript
复制
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);
}
EN

回答 4

Stack Overflow用户

发布于 2009-10-22 14:17:27

您不能修改引用。即使您将其替换为指针,修改指针也不会修改指向的对象。相反,您需要完成引用--只需交换字段即可。

代码语言:javascript
复制
void myString::swap(myString &from)
{
    std::swap( stringLen, from.stringLen );
    std::swap( stringPtr, from.stringPtr );
}

上面使用的是user sbi在注释中建议的std::swap()。这完全等同于下面(只是为了说明,不要重新发明STL):

代码语言:javascript
复制
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
}

即使在调用自交换时,这两种方法也可以正常工作:

代码语言:javascript
复制
myString string;
string.swap( string );
票数 2
EN

Stack Overflow用户

发布于 2009-10-22 15:32:02

关于myString::swap()函数中的错误,您已经得到了一些很好的答案。然而,我想添加另一个。这个函数有很多错误,我一开始发现很难考虑从哪里开始。但后来我意识到你在一些基本问题上失败了,我想指出的是:

通常,需要一个名为swap的函数来执行其任务

O(1)

  • 中的
  1. ,没有抛出异常。

(是的,我知道,也有例外:std::tr1::array<>::swap()。但这些都应该是非常合理的。)您的实现在两个帐户上都失败了。它是O(n) (strcpy),并且可能抛出一个异常(new) --它这样做是不必要的,而且没有正当理由。

当您查看myString时,您将看到它只有两部分成员数据,这两部分都是内置类型。这意味着交换这个类的两个对象非常简单,同时遵循上面提到的约定:只交换成员数据。这就像对它们调用std::swap一样简单:

代码语言:javascript
复制
void myString::swap(myString &from)
{
  std::swap(this->stringPtr,from.stringPtr);
  std::swap(this->stringLen,from.stringLen);
}

这是永远不会失败的(交换两个指针和两个整数不会失败),用O(1)执行,非常容易理解(好吧,一旦您掌握了这种交换,不管怎样,它是实现特定于类的swap函数的惯用形式),它由两行代码调用标准库中经过良好测试的东西组成,而不是由8行代码进行容易出错(在您的例子中是错误的)的手动内存管理。

注意1:一旦你这样做了,你应该指定std::swap来调用你的类的实现:

代码语言:javascript
复制
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

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2009-10-22 14:21:19

from = new char[stringLen+1];应为from.stringPtr = new char[stringLen+1];。另外,记得在分配新内存之前释放以前分配的内存。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1605312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档