简体   繁体   English

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

[英]Can't push_back a class containing an ofstream pointer to a vector

I've come across a weird segfault while trying to push a class containing a pointer of an ofstream to a vector. 我在尝试将包含ofstream的指针的类推送到向量时遇到了奇怪的段错误。 I have narrowed the problem down to the simplest test case possible: 我已将问题缩小到最简单的测试用例:

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 main.cpp

#include <vector>
#include "Test.h"

int main() {
    Test test("hello.txt");
    std::vector<Test> vec;
    vec.push_back(test); // segfaults
}

I think that the segfault has to do with the destructor for Test, but I'm not sure why. 我认为该段错误与Test的析构函数有关,但我不确定为什么。 The segfault occurs when I use emplace_back as well. 当我也使用emplace_back时,将发生段错误。

The first problem that your code suffers from is that you are not following The Rule of Three . 您的代码遭受的第一个问题是您没有遵循“三法则”

However, your problem is deeper than what is suggested to follow The Rule of Three. 但是,您的问题要比遵循“三则法则”所建议的要深。

Say your class had a different member variable than std::ofstream* . 假设您的班级成员变量与std::ofstream*

class Test {
  public:
    Test(int in) : ptr(new int(in)) {}
    ~Test();
private:
    int* ptr;
}

You can update that class to follow the rule of three by making the sure that you do the right thing in the copy constructor and the copy assignment operator. 通过确保在复制构造函数和复制赋值运算符中执行正确的操作,可以更新该类以遵循三个规则。 In both of those, you'll have to use something along the lines of: 在这两种方法中,您都必须使用以下方法:

ptr = new int(*copy.ptr);

That works for most types. 适用于大多数类型。 However, that does not work for std::ofstream since std::ofstream does not have a copy constructor or a virtual function that can return a pointer by cloning the object. 但是,这对于std::ofstream不起作用,因为std::ofstream没有复制构造函数或virtual函数可以通过克隆对象返回指针。

In your case, neither of the following is an option. 在您的情况下,以下两项都不是选项。

ofstr = new ofstream(*copy.ofstr);
ofstr = copy.ofstr->clone();

To get around that problem, you can use std::shared_ptr<std::ofstream> . 要解决该问题,可以使用std::shared_ptr<std::ofstream>

class Test {
  public:
    Test(std::string path);
    ~Test();
  private:
    std::shared_ptr<std::ofstream> ofstr;
}

When you do that, not only do you fix your problem but also, you can let the compiler generated destructor, copy constructor, and copy assignment operator do the right thing. 当您这样做时,不仅可以解决问题,还可以让编译器生成的析构函数,复制构造函数和复制赋值运算符做正确的事情。 Your class definition can be simplified to: 您的类定义可以简化为:

class Test {
  public:
    Test(std::string path);
  private:
    std::shared_ptr<std::ofstream> ofstr;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM