如果在类 temlpate 中使用,fstream 是否会在编译时通过读取和写入来访问 hardrive?

Does fstream access the hardrive with read and writes during compile time if used within a class temlpate?

本文关键字:读取 hardrive 访问 编译 temlpate 是否 fstream 如果      更新时间:2023-10-16

请考虑此类模板的以下代码片段...

template<class T>
class FileTemplate {
private:
std::vector<T>   vals_;
std::string  filenameAndPath_;
public:
inline FileTemplate( const std::string& filenameAndPath, const T& multiplier ) :
filenameAndPath_( filenameAndPath ) {
std::fstream file;
if ( !filenameAndPath_.empty() ) {
file.open( filenameAndPath_ );
T val = 0;
while ( file >> val ) {
vals_.push_back( val );
}
file.close();
for ( unsigned i = 0; i < vals_.size(); i++ ) {
vals_[i] *= multiplier;
}
file.open( filenameAndPath_ );
for ( unsigned i = 0; i < vals_.size(); i++ ) {
file << vals_[i] << " ";
}
file.close();
}
}
inline std::vector<T> getValues() const {
return vals_;
}
};

当在 main 中使用时,下半部分用以下预填充的文本文件注释掉:

值.txt

1 2 3 4 5 6 7 8 9

int main() {
std::string filenameAndPath( "_build/values.txt" );
std::fstream file;
FileTemplate<unsigned> ft( filenameAndPath, 5 );
std::vector<unsigned> results = ft.getValues();
for ( auto r : results ) {
std::cout << r << " ";
}
std::cout << std::endl;
/*
FileTemplate<float> ft2( filenameAndPath, 2.5f );
std::vector<float> results2 = ft2.getValues();
for ( auto r : results2 ) {
std::cout << r << " ";
}
std::cout << std::endl;
*/
std::cout << "nPress any key and enter to quit." << std::endl;
char q;
std::cin >> q;
return 0;
}

我通过调试器运行此代码,确保屏幕和文件的输出都更改为

值.txt- 覆盖的是 -

5 10 15 20 25 30 35 40 45 

然后假设我不更改任何代码只是停止应用程序的调试或运行,假设我再运行 2 次,输出分别为:

值.txt- 迭代 2 和 3

25 50 75 100 125 150 175 200 225 250
125 250 375 500 625 750 875 1000 1125 1250

到目前为止还不错;现在让我们将文本文件中的值重置回默认值,并取消注释该类模板的第二个实例化,用于乘数值为 2.5f 的浮点数,然后运行 3 次。

值.txt- 重置为默认值

1 2 3 4 5 6 7 8 9

-迭代 1,2 和 3 无符号和浮点数 乘数分别为<5,2.5>。 5 表示无符号,2.5 表示浮点


- 迭代 1

库特:

5 10 15 20 25 30 35 40 45
12.5 25 37.5 50 62.5 75 87.5 100 112.5

值.txt:

12.5 25 37.5 50 62.5 75 87.5 100 112.5


- 迭代 2

库特:

60
150 12.5 62.5 93.75 125 156.25 187.5 218.75 250 281.25

值.txt:

150 12.5 62.5 93.75 125 156.25 187.5 218.75 250 281.25


- 迭代3

库特:

750 60
1875 150 12.5 156.25 234.375 312.5 390.625 468.75 546.875 625 703.125

值.txt:


1875 150 12.5 156.25 234.375 312.5 390.625 468.75 546.875 625 703.125

我想到了几个问题:关于该程序的相同行为,这是双重的。

第一个也是主要的问题是:考虑到这是一个类模板并且构造函数是内联的,文件读取和写入调用是否在编译时完成?

运行调试器几次后;为什么输出会增加文件中的值数?我从 9 开始,但经过大约一次迭代后有 10 个,然后是 11 个。


这部分只是为了好玩,如果你想回答:

第三个也是最后一个问题是基于意见的,但仅用于教育目的,因为我想看看社区对此的看法:这种类型的编程的利弊是什么?潜力和极限是什么?他们有任何实际的实际应用和生产效益吗?

就其他问题而言。主要问题是在执行第二个file.open语句时没有截断文件,您需要:

file.open( filenameAndPath_, std::fstream::trunc|std::fstream::out );

正在发生的事情是,当您从包含浮点的文件中读取unsigned int时,它只读取第一个数字(例如 12.5)直到小数位,然后停止(例如,仅读取 12) ,因为该行上没有其他看起来像unsigned int的文本。这意味着它只读取数字 12,然后将其乘以 5 得到 60,并将其写入文件。

不幸的是,由于您在写入 60 时没有截断文件,因此它会将原始文本留在末尾,该文本在下一个读取循环中被解释为其他数字。因此,12.5在文件中显示为60 5

流缓冲区 从流中提取尽可能多的字符,并将它们插入到 sb 指向的流缓冲区对象(如果有)控制的输出序列中,直到输入序列用尽或函数无法插入到 sb 指向的对象中。

(http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/)