在尝试将包含ofstream的指针的类推送到向量时遇到了奇怪的段错误。我已将问题缩小为最简单的测试用例:
Test.h
#ifndef __TEST_
#define __TEST_
#include <fstream>
#include <string>
class Test {
public:
Test(std::string path);
~Test();
private:
ofstream* ofstr;
}
#endif
Test.cpp
#include "Test.h"
Test::Test(std::string path) {
ofstr = new ofstream(path, std::ios::app);
}
Test::~Test() {
delete ofstr;
}
main.cpp
#include <vector>
#include "Test.h"
int main() {
Test test("hello.txt");
std::vector<Test> vec;
vec.push_back(test); // segfaults
}
我认为该段错误与Test的析构函数有关,但我不确定为什么。当我也使用emplace_back时,就会发生段错误。
答案 0 :(得分:2)
您的代码遭受的第一个问题是您没有遵循The Rule of Three。
但是,您的问题比遵循“三则法则”的建议要深。
假设您的班级的成员变量不同于std::ofstream*
。
class Test {
public:
Test(int in) : ptr(new int(in)) {}
~Test();
private:
int* ptr;
}
通过确保在复制构造函数和复制赋值运算符中执行正确的操作,可以更新该类以遵循三个规则。在这两种方法中,您都必须使用以下方法:
ptr = new int(*copy.ptr);
适用于大多数类型。但是,这对std::ofstream
不起作用,因为std::ofstream
没有复制构造函数或virtual
函数可以通过克隆对象返回指针。
在您的情况下,以下两项都不是选择。
ofstr = new ofstream(*copy.ofstr);
ofstr = copy.ofstr->clone();
要解决该问题,可以使用std::shared_ptr<std::ofstream>
。
class Test {
public:
Test(std::string path);
~Test();
private:
std::shared_ptr<std::ofstream> ofstr;
}
这样做时,不仅可以解决问题,而且还可以让编译器生成的析构函数,复制构造函数和复制赋值运算符做正确的事情。您的类定义可以简化为:
class Test {
public:
Test(std::string path);
private:
std::shared_ptr<std::ofstream> ofstr;
}