Почему глобальная переменная ofstream в заголовке не может записывать файлы в C ++? - PullRequest
1 голос
/ 24 сентября 2019

1. Например, есть a.cpp, b.h, b.cpp b.h

чч:

#ifndef UNTITLED_B_H
#define UNTITLED_B_H
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
class b {
    ofstream b_out; // here
public:
    explicit b();
    int b_write(const string &message);
};
#endif //UNTITLED_B_H

b.cpp:

#include "b.h"
b::b(){        
    b_out.open("test.txt");
}
int b::b_write(const string &message){
    b_out<<message;
}

a.cpp:

#include "b.h"
int main(){
    b *b_object = new b();
    b_object->b_write("hello happy b");
}

этот код не содержит ошибок и файл создан.но сообщение не распечатывается.

Однако перенесите код определения ofstream (// здесь отмечен) в b.cpp, как показано ниже.

bh:

#ifndef UNTITLED_B_H
#define UNTITLED_B_H
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
class b {
public:
    explicit b();
    int b_write(const string &message);
};
#endif //UNTITLED_B_H

b.cpp:

#include "b.h"
ofstream b_out; //here
b::b(){
    b_out.open("test.txt");
}
int b::b_write(const string &message){
    b_out<<message;
}

в этом случае сообщение печатается хорошо.

но я не понимаю различий между ними.

кто-нибудь может мне помочь?

спасибо!

1 Ответ

3 голосов
/ 24 сентября 2019

Вы создаете свой экземпляр b в куче

b *b_object = new b();

Это означает, что вы несете ответственность за его удаление, когда вы больше не используете его

b* b_object = new b();
/* use b_object here */
delete b_object;

Безвызов delete, деструктор не вызывается, то есть деструктор ofstream не вызывается, что вызвало бы сброс потока, записывающего сообщение в файл.Когда вы создали экземпляр ofstream как глобальный внутри вашего b.cpp, компилятор отвечал за вызов его деструктора, поэтому он работал.

Не управляйте памятью самостоятельно, используйтеумный указатель

#include <memory>

auto smart_ptr = std::make_unique<b>();
smart_ptr->b_write("hello happy b");

Он будет вызывать delete для вас.

Еще лучше, на самом деле нет причин, по которым вам следует выделять память в куче, если вы создали своюэкземпляр b в стеке, компилятор сделает все за вас, благодаря RAII.

int main(){
    b b_object;
    b_object.b_write("hello happy b");
}
...