ifstream成员的内部类构造函数返回无效的fstream

时间:2014-03-05 10:47:08

标签: c++ access-violation ifstream

我有一个内部类的类,它有一个ifstream成员。执行代码时会在TestDataHelper::getNextLine() if(!datafile->eof())处抛出AccessViolationException。

调试向我展示了构造函数正常工作。创建文件并读取第一行。但是当我在完成赋值后检查数据文件时(在TestDataHelper helper = TestDataHelper("data.csv");之后),数据文件将变为无效指针。

代码:

IfstreamTester.h

#include <vector>
#include <iostream>
#include <string>
#include <sstream>

class IfstreamTester
{
public:
    IfstreamTester(void);
    ~IfstreamTester(void);

    void doStuff();

private:
    std::ifstream file;

    class TestDataHelper{
    private:
        std::ifstream *datafile;
    public:
        TestDataHelper(std::string filename);
        ~TestDataHelper();
        std::vector<double>* getNextLine();
    };
};

IfstreamTester.cpp

#include "IfstreamTester.h"

using namespace std;

IfstreamTester::IfstreamTester(void)
{}

IfstreamTester::~IfstreamTester(void)
{}

void IfstreamTester::doStuff()
{
    TestDataHelper helper = TestDataHelper("data.csv");
    // for every line in the file
    vector<double>* v;
    do
    {
        v = helper.getNextLine();
        cout << v << endl;
        delete v;
    } while(v != NULL);
}

IfstreamTester::TestDataHelper::TestDataHelper(std::string filename)
{
    datafile = new ifstream(filename.c_str());
    // read the header line
    string line;
    getline(*datafile, line);
}

vector<double>* IfstreamTester::TestDataHelper::getNextLine()
{
    if(!datafile->eof())
    {
        // readline
        string line = "";
        getline(*datafile, line);
        string delimiter = ",";
        vector<double>* res = new vector<double>();
        size_t pos = 0;
        // and tokenize line into vector of doubles
        while ((pos = line.find(delimiter)) != std::string::npos)
        {
            stringstream conv;            
            double token;
            conv << line.substr(0, pos);
            conv >> token;
            res->push_back(token);
            line.erase(0, pos + delimiter.length());
        }
        return res;
    }
    else
    {
        return NULL;
    }
}

IfstreamTester::TestDataHelper::~TestDataHelper()
{
    datafile->close();
    delete datafile;
}

和主要:

#include "IfstreamTester.h"

void main()
{
    IfstreamTester s = IfstreamTester();
    s.doStuff();
}

有人知道为什么会这样吗?

编辑:我正在使用Microsoft Visual Studio 2008 Express

3 个答案:

答案 0 :(得分:1)

while(v != NULL)看起来相当错误。你的意思是按如下方式编写你的循环吗?

vector<double>* v = NULL;
do
{
    v = helper.getNextLine();
    cout << v << endl;
    delete v;
} while(v != NULL);

答案 1 :(得分:1)

你的编译器没有给你任何帮助。它应该是puking,告诉你std::ifstream不可复制,因此也应隐式删除其包含父项IfstreamTester的默认复制构造函数。

我不知道你正在使用什么工具链,但clang ++ 3.3和g ++ 4.7都对此有所了解。您的编译器显然允许它通过复制省略假设,然后在调试中实际上无法删除副本。添加成员复制std::ifstream成员的复制构造函数,或将main()声明为:

int main()
{
    IfstreamTester s;
    s.doStuff();
}

您的代码中的非标准void main()声明让我(可能不正确)推断您正在使用MS或Borland工具链。允许这样做的人(包括奇数main()和不可复制的std::ifstream成员)都不符合规则。

答案 2 :(得分:0)

我尝试使用g ++ 4.6.3编译它:

我必须添加#include <fstream>并将IfstreamTester s = IfstreamTester();更改为IfstreamTester s;