C / C ++通过调用reference或直接释放指针

时间:2014-09-08 07:58:31

标签: c++ c pointers

struct State {
    int* maxLiters;
    int* nowLiters;
} parentState;

void makeState(State& s) {
    if ((s.maxLiters = (int*)malloc(cups*sizeof(int))) == nullptr) {
        error();
    }
    if ((s.nowLiters = (int*)malloc(cups*sizeof(int))) == nullptr) {
        error();
    }
}

void delState(State& s) { // or delState(State s) ?
    free(s.maxLiters);
    free(s.nowLiters);
}

我一直在使用C语言进行编码,而且我真正开始使用C ++。对于使用' malloc'。

表示歉意

在' delState'函数,我通过引用传递了结构。我有点不确定是否也可以按值传递此值,如评论中所示。在C中,我通常会用指针做这个,以便始终如一地放置一个'&'调用制作和删除功能时。由于使用参考参数我不应该键入'&',我很想制作一个纯值的call-by-value函数。考虑一下我自己确实说好了'因为无论是通过参考还是通过价值,“免费”是免费的。函数将获得相同的内存地址。但我只是担心,因为我从未这样做过。

有用的是任何澄清,提前感谢。

3 个答案:

答案 0 :(得分:4)

如果你想使用C ++,最好学习做事的“C ++方式”。在这种情况下,您不应该真正调用函数来为您创建和删除状态,而应该使用类构造函数和析构函数。而且,通常最好使用std :: vector而不是使用数组。对于您的示例,这看起来像:

class State {
public:
    State (size_t cups) 
       : maxLiters(cups), nowLiters(cups) //reserve "cups" amount of space in the vectors
    { }

    ~State () =default; //default destructor, will call the vector destructors and delete the data automatically
    State (const State &other) =default //default copy constructor, will copy the contents of the vectors into a new State object
    State &operator= (const State &other) =default //default assignment operator, will overwrite the contents of this object with the new one

    std::vector<int> maxLiters;
    std::vector<int> nowLiters;    
};

然后,如果要处理内存不足错误,可以在创建状态对象时执行此操作:

try
{
    State s(12);
    ...
}
catch (std::bad_alloc &ba)
{
    error();
}

但是,捕获bad_alloc异常通常没有意义,因为从类似的范围内恢复很难到不可能,特别是如果抛出异常时某些数据结构被破坏了。

现在您的类管理堆分配的数据,您应该考虑复制和分配此类对象应该意味着什么,并定义复制构造函数和赋值运算符重载,如果默认值不会为您剪切它。这称为Rule of Three

你还应该考虑通过将它们声明为私有并为它们提供getter / setter来封装你的向量。即使您为了界面一致性声明了getter和setter,这也是很好的做法。

答案 1 :(得分:2)

我认为使用构造函数/析构函数以及向量的建议是解决这个问题时应该采取的建议。但是,我认为在这种情况下你应该看两件重要的事情,因为在某些时候你可能需要手动分配。

RAII-Idiom(Resource Allocation Is Initialization

总结它的用途意味着什么:你永远不会使用函数来分配/释放资源,但让构造函数/析构函数处理它。在你的情况下,它意味着你创建一个状态的构造函数,它执行数组的分配,以及一个析构函数,它执行free。我提到这个,即使我同意之前的答案,建议你使用矢量,因为我认为,如果你处于必须进行手动分配的情况,我很高兴知道。你不应该像你那样使用分配/自由函数,因为c ++有例外,所以你不能保证到达调用自由函数的代码。因此,您还必须在异常例程中处理free,而在大多数情况下会自动调用析构函数。

智能指针

如果您想进行尽可能少的更改,这些也可能是您的选择。在c ++中,如果可以的话,你应该总是使用智能指针(这几乎总是如此)。在新标准中,有两种类型的智能指针:唯一指针和共享指针。两者都应该得到很长的解释,但我会推迟(unique pointershared pointer)。阅读那些甚至超出我所链接的定义的内容是明智的,因为这两者非常强大。唯一指针允许您拥有一个无法复制的指针,并且一旦超出范围,它将处理它指向的对象的释放。共享指针存储引用计数,并在计数达到0时释放它指向的对象。结合RAII,这些指针通常允许您编写代码而无需显式手动分配,这通常是您在c ++中所需要的。如果你不能使用c ++ 11中的智能指针,你应该考虑boost's smart pointers

答案 2 :(得分:1)

  

块引用    我一直在使用C语言进行编码,而且我真正开始做C ++

您需要将C++写为C++,尽管您在某些方面也负责内存管理(即通常没有垃圾回收),但您通常不会直接删除内存,但使用提供的库来为您处理内存。

Whwatever cups,看起来你的State类包含两个向量。

class State
{
     // note these members are private

   std::vector< int > maxLiters_;
   std::vector< int > nowLiters_;

 public:
   explicit State( size_t cups )
         : maxLiters_( cups )
         ,  nowLiters_( cups )
   {
   }

   std::vector<int> const& maxLiters() const
  {
    return maxLiters_;
   }

   std::vector< int > const& nowLiters() const
  {
      return nowLiters ;
  }
};

int main()
{
    State state( 6 );

   // whatever
}

无需任何东西。这些载体归班级所有。如果您复制班级,您的矢量将被复制以制作新的副本。如果你想要不同的语义,你可能会使用shared_ptr

C++是一种不同的语言,您需要学会使用它,而不是考虑如何在C中实现它。 (或Java,C#,Python,Perl或任何其他语言)。

顺便提一下你的实现(如果删除引用等,即使是C),如果第一个malloc成功但第二个失败,则会出现问题。你知道哪一个真的失败了吗?你知道是否free是第一个吗?

你可以通过在尝试分配任何东西之前设置指向nullptr的指针来解决这个问题,但是你没有做到。