了解指针和错误的内存分配?

时间:2014-02-02 20:09:14

标签: c++ pointers memory-management exc-bad-access dynamic-arrays

免责声明:我对C ++非常非常新。两年前我参加了一个班级,现在我正在上另一个班级,所以试图回到心态是很困难的。话虽这么说,我知道我的代码非常糟糕;我想要帮助和建设性的批评,所以请避免彻底抨击,因为我知道我真的不知道我在做什么。

目标:我正在编写一个程序,它接受两个形式为{1 2 3}(任意大小)的用户输入集,并对它们执行一些操作。但是我只是在阅读它们时遇到了麻烦。这是一个头文件的快速片段,显示了我将要问的函数:

class Set{

  public:

    Set();                  //Constructor for empty set.
    Set(int element);       //Constructor for set of one element
    ~Set();

    unsigned int getSize() const;                          
    int operator[](const int e) const;  

    friend ostream& operator<<(ostream& oss, const Set& output);   
    friend istream& operator>>(istream& ss, Set& target);         

  private:

    int size;
    int *elements[];        
    void resize(unsigned int new_size);
};

还有更多,但我只是向你展示所有必要的东西。

对于赋值,我们创建一个名为Set的类,但该集必须存储为数组。我们为每个Set都有一个指针数组(即Set类带有int * elements [])。我们需要重载“&gt;&gt;”运算符将用户输入转换为Set。用户输入两个集。我们假设用户足够聪明,可以以{1 2 3 4}的确切形式输入,但它可以是任何大小。这是我的重载&gt;&gt;。

istream& operator>>(istream& ss, Set& target){ 

  //The constructor Set target; creates an empty Set with array size=0.

  char c;      

  if (ss.peek()=='}') ss >> c; 
  if (ss.peek()==EOF) ss >> c;

  ss >> c;     //First we read in the '{' character.
  int num;

  while (ss.peek()!='}'){
    ss >> num;
    target.resize(target.getSize()+1); 
    *target.elements[target.getSize()-1]=num;
  };
  return ss;
};

getSize()只是一个返回值“size”的函数。上面代码片段的目标是创建一个空Set,然后对于介于“{”和“}”之间的每个int,我们将数组的大小调整为1,然后将该int放入数组的下一个元素中。此外,对于我来说,流仍然像指针一样抽象,所以这就是为什么这似乎有点蛮力。

我遇到的问题是调整大小。我希望 - 显然 - 调整大小以改变大小,但它不允许这样做。我想要完成的是调整大小以将被调用的Set的*元素指针更改为指向具有new_size元素数量的新数组。然后我想释放该指针以避免内存泄漏。

void Set::resize(unsigned int new_size){

  if (size!=new_size){
      int *newelements = new int[new_size];

      for (int i=0; i<new_size || i<size; i++){
          newelements[i] = *elements[i]; 
      };

      *elements = newelements;
      delete newelements;

      if (size>new_size) size=new_size;
   };

};

我知道的一件事是错的:当我在“&gt;&gt;”的定义中调用newset.resize时,

newelements[i] = *elements[i];
由于“num”尚未分配给* newset.elements [i],

行正试图分配一些尚不存在的东西。但是,如果我尝试在“&gt;&gt;”中切换这些顺序所以它就这样......

*target.elements[target.getSize()]=num;
target.resize(target.getSize()+1); 

...这应该没有意义,因为目标数组的大小是0,所以我不能说target [0] = num;

我知道的另一件事是错误的:我使用指针的方式必须错误,因为如果我在调整大小定义中尝试说size = new_size ,我收到“EXC_BAD_ACCESS”错误。实际上,如果我按原样运行,我会收到相同的错误消息。

此外,在作业中,我们被告知“如果new_size严格小于大小,则调整大小应该只更新大小。”我不明白这是如何工作的。如果我们必须从size = 0的初始化数组开始,那么我们怎样才能让它更大呢?

我希望我已经包含足够的内容以获得一些帮助。我感谢任何有助于我理解指针以及如何使用它们的东西。非常感谢你!

1 个答案:

答案 0 :(得分:0)

我不确定我是否拿起了所有东西,但是扫描了代码:

  1. 声明int *elements[];在C ++中是非法的,尽管有些编译器允许它作为扩展。 您必须指定数组大小。 如果我用gcc编译,它会告诉我:

      

    警告:ISO C ++禁止零大小数组'元素'[-Wpedantic]

         

    int * elements [];

  2.         2. if (size!=new_size)行始终为true,除非size不等于new_size。      您最有可能只在new_size 更大而不是size时调整数组大小。

    3. i<new_size || i<size应该只是i<size

    4.在newelements[i] = *elements[i];中,*elements[i]相当于*(elements[i]) (*elements)[i],您确定这是您想要的吗?

    5。

    *elements = newelements;
    delete newelements;
    

    第一行使elements的第一个元素(指针)指向新分配的内存。第二行然后删除该内存,所以现在elements的第一个元素现在指向释放的内存。那不是你想要的。 请记住,当您为指针指定指针时,它会使两个指针指向同一个内存。您需要做的是删除内存,然后将指针指定为指向新分配的内存。

    6.还要记住delete []delete不同。删除内存块时,您需要使用delete []

    希望这一切都是为了学习目的。在真正的C ++代码中,您将改为使用std::vector