从数组中删除指针

时间:2012-05-05 05:35:07

标签: c++

我是C ++的新手,我遇到的这个问题让我在过去的2个小时里难以接受。我要做的是创建一个指向我的类Word对象的指针数组,这样一个二维数组,即**wordPtrList。然后我需要删除数组中某些对象的内存并将其指针设置为null。我写了一个较小的版本,我想在下面完成。

int main()
{
    char *cArray;
    cArray = new char[4];
    int i;

    for (i = 0; i < 3; i++)
        cArray[i] = 'a';

    cArray[i + 1] = '\0';   //cArray is a null terminated string

    Word **wordPtrList;
    wordPtrList = new Word* [3];

    for (i = 0; i < 3; i++)
    {
        wordPtrList[i] = new Word(cArray);
    }

    wordPtrList[1]->del();
    delete wordPtrList[1];
    wordPtrList[1] = '\0';

    return 0;
}

class Word
{
private:
    char* ptr_;
    int len_;
public:
    Word(const char* word)
    {
        len_ = strlen(word);
        ptr_ = new char[len_];      
        strcpy(ptr_, word);
    }
    ~Word()
    {
        delete [] ptr_;
        ptr_ = 0;
    }


    void del()
    {
        delete [] ptr_;
        ptr_ = 0;
        return;
    }

};

当我这样做时,我得到:

  

正常阻止后检测到的调试错误堆损坏

这是在Windows 7上的VS 2010中。

所以我要问的是,如何删除对象的内存以便将wordPtrList[1]设置为Null?

4 个答案:

答案 0 :(得分:2)

看看这段代码:

for (i = 0; i < 3; i++)
    cArray[i] = 'a';
cArray[i + 1] = '\0';   //cArray is a null terminated string

问题出在使用i+1作为索引的最后一行,它超出了范围,就像循环退出时一样,i的值已经{{1} };这意味着3将成为i+1,当您将4分配为:{/ p>时,cArray无法成为有效索引

cArray = new char[4]; //taken from your code

解决方案是:

cArray[i] = '\0';   //Now, it is correct. Here i is equal to 3

即,使用i代替i+1;或者只使用3


在C ++中,你可以std::fill而不是手动循环,如:

std::fill(cArray, cArray + 4, 'a'); //done

更好地避免尽可能使用char*new,并且更喜欢使用std::string

答案 1 :(得分:2)

您正在为cArray分配4个字节(意味着您可以访问写入0到3的字节),然后写入cArray [4]。您还在Word构造函数中分配了一个太小的字节。

char *cArray;
cArray = new char[4];
int i;

for (i = 0; i < 3; i++)
    cArray[i] = 'a';
cArray[i] = '\0';   //cArray is a null terminated string - i is now 3

 Word(const char* word)
 {
    len_ = strlen(word);
    ptr_ = new char[len_ + 1];      
    strcpy(ptr_, word);
 }

应该这样做。

答案 2 :(得分:0)

代码中有两个明显的逐个错误(当你离开第一个循环时变量i的值是什么?)当你调用strlen时你是否记得考虑过null终止符所需的空间?)。

另请注意,c字符串不是“空终止”,它们是“NUL终止”,大写字母只有一个“L”。 NUL是ASCII控制字符的名称,所有位都设置为零,并在C ++中用'\0'表示。 在一个地方你使用NUL字符作为空指针,虽然这在技术上是正确的(因为C ++语言的设计错误),但最好还是明白这两个概念是完全不同的。

答案 3 :(得分:0)

正如其他人所说,你基本上是在访问超出数组范围的数组索引。

我会选择Nathan Wiebe的解决方案。

将来,当您可以选择执行此操作时,建议使用std::vector<T>,因为这样可以在动态可调整大小的数组中存储您希望的任何类型。换句话说,如果你不访问向量边界之外的索引,你可以这样做:

std::vector< char* > str;

for( size_t i = 0; i < str.size(); ++i )
{
   str.push_back( 'a pointer to a block of memory consisting of characters' ); 
}

class Word
{
public:
    Word( const char* str )
    {
        mStrs.push_back( str );
    }
    ~Word( void )
     {
         for( size_t i = 0; i < mStrs.size(); ++i )
         {
             if( mStrs[ i ] )
             {
                 delete mStrs[ i ];
                 mStrs[ i ] = NULL;
             }
         }

         mStrs.clear();
     }

private:
    void del( size_t index )
    {   
         if( index > mStrs.size() )
         {
              //error - throw new exception or something
         }

         delete mStrs[ index ];
    }

    std::vector< const char* > mStrs;

};