【问题标题】:Can't push_back a class containing an ofstream pointer to a vector不能 push_back 包含指向向量的 ofstream 指针的类
【发布时间】:2018-07-27 21:08:32
【问题描述】:

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

【问题讨论】:

  • @πάνταῥεῖ 我正在更改欺骗目标,因为它是违反三规则的规则,因为 OP 有一个指向流的指针
  • 由于违反了三规则,您的指针被双重删除。那是未定义的行为。
  • 您的代码段错误,因为 main 中的变量 test 和向量元素都有一个指向同一元素的指针,并且当它们被破坏时,您正在破坏 ofstream 元素两次。如果您希望Test 类的多个对象共享指向 ofstream 的指针,则应使用std::shared_pointer&lt;std::ofstream&gt;,您可以在此处阅读更多信息en.cppreference.com/w/cpp/memory/shared_ptr
  • 完全不相关的旁注:任何地方的前导下划线和双下划线都有特殊含义。 What are the rules about using an underscore in a C++ identifier? 中有关此内容的更多信息很少会违反此规则,但一旦发生,结果可能会令人费解。

标签: c++ vector stl ofstream


【解决方案1】:

您的代码遇到的第一个问题是您没有关注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&lt;std::ofstream&gt;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多