我有一个内部类的类,它有一个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
答案 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;