避免(!is_eof)

时间:2012-02-07 07:45:09

标签: c++ stream scope while-loop state-machine

我正在使用(C ++)库,其中对象需要使用流初始化。随库提供的示例代码使用以下代码:

// Declare the input stream
HfstInputStream *in = NULL;

try 
{
    // This sets up the special stream object for the later object (see below)
    in = new HfstInputStream("pathToFile.hfsto");
} 
// catch errors...
// {omitted}

// Initialize the object
while (not in->is_eof()) {
    if (in->is_bad()) 
    {
        std::cerr << "ERROR: Stream cannot be read." << std::endl;
        exit(1); 
    }
    // Here we initialize the object using the stream
    HfstTransducer t(*in);
}

我的问题是,由于作用域,此对象不能在while循环之外使用。我必须用流声明它(据我所知),所以我不能声明然后用循环内的流初始化它。

我的问题是(1)我错了吗?我能不能以某种方式在循环之外声明它? (2)是否有另一种(更好的)方法可以完全避免循环。例如,如果我使用try / catch并捕获异常。

我对C ++很陌生并希望找到最佳实践,所以请让我知道它是什么。感谢。

另外,为了清楚起见,我正在寻找一个使用该对象的持久版本的类,所以每次我需要使用它时,我都不必经常创建/销毁这些对象。

PS:here's a link to the documentation for the object if it is relevant

编辑:如果我尝试在循环外声明变量然后初始化它我得到一个错误

HfstTransducer t;
while (not in->is_eof()) {
    t(*in);
}
// ERROR: main.cpp:47:0 main.cpp:47: error: no match for call to '(hfst::HfstTransducer) (hfst::HfstInputStream&)'

我是否尝试错误地初始化它?

1 个答案:

答案 0 :(得分:2)

为了达到你所需要的,你必须有一个指向在while范围之外声明的对象的指针,如:

//Declare the pointer to the object outside the while score. This way it will be available to you even outside of the while
HfstTransducer* t = 0;
// Initialize the object
while (not in->is_eof()) {
    if (in->is_bad()) 
    {
        std::cerr << "ERROR: Stream cannot be read." << std::endl;
        exit(1); 
    }
    // Here we initialize the object using the stream only if it's not already been initialized before
    // thanks to Necrolis for the observation
    if(t == 0)
        t = new HfstTransducer(*in);
}

这会将HfstTransducer类型的对象声明并初始化到堆中。这意味着在离开作用域后不会自行调用析构函数,但是必须通过调用显式调用它:

delete t;

编辑:回答有关指针与普通对象的一般问题:

这是C / C ++的一个非常重要的部分。 可以看到一篇更好地解释这一点的文章here

如果我通过这样做来解释一下:

HfstTransducer t;

您正在声明该类型的对象并将其放入堆栈中。它的使用寿命仅持续到示波器结束。您无法在范围之外访问它,因为一旦范围结束就会调用析构函数。

另一方面

HfstTransducer*t = new HfstTransducer();

将t初始化为HfstTransducer类型的对象并将其放在堆中。关于堆的内容是指上面的文章,但它基本上是操作系统为您的程序分配的内存。在C ++中,您需要使用运算符 new 在堆中寻找内存,并使用 delete 运算符释放它。在C中,您可以使用 free() malloc()函数实现相同的功能。

除非你明确地调用它的析构函数,否则堆中的某些东西在程序的整个持续时间内都是活着的。正如您在示例中所做的那样,可以通过调用 delete t;

来完成

如果不这样做会导致所有C / C ++程序员必须面对的问题,即所谓的内存泄漏。这基本上是你认为是免费的记忆,但不是因为你忘了删除/释放它。