无法push_back一个包含指向向量的ofstream指针的类

时间:2018-07-27 21:08:32

标签: c++ vector stl ofstream

在尝试将包含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时,就会发生段错误。

1 个答案:

答案 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;
}