提问者:小点点

作为类成员的std::ofstream是否删除复制构造函数?


下面的代码仅在我移除类Test的析构函数的定义或移除std::OfStream成员时进行编译。 否则,我会收到一个错误,告诉我Test的复制构造函数已被删除。

有人能解释一下这是为什么吗? 谢谢!

#include<fstream>
#include<vector>

class Test {
public:
    Test() {};
    ~Test() {};
    std::ofstream ofs;

};

int main() {
    std::vector<Test> vec;
    vec.emplace_back(Test());
} 

错误消息:

Error   C2280   'Test::Test(const Test &)': attempting to reference a deleted function

编辑:如果只是因为std::ofstream不可复制而删除测试的复制构造函数,为什么要编译?:

#include<fstream>
#include<vector>

class Test {
public:
    Test() {};
    //~Test() {};
    std::ofstream ofs;

};

int main() {
    std::vector<Test> vec;
    vec.emplace_back(Test());
}

共3个答案

匿名用户

有一个已删除的复制构造函数:std::ofstream。 当您将它放在向量中时,测试将被尝试复制。 这会失败,因为没有std::ofstream的复制构造函数。 您需要定义自己的复制构造函数来处理ofs:

#include<fstream>
#include<vector>

class Test 
{
public:
    Test() {};
    ~Test() {};
    Test(const Test& other) 
    {
    // does not make sense of course
    };
    std::ofstream ofs;
};

int main() {
    std::vector<Test> vec;
    vec.emplace_back(Test());
} 

匿名用户

如果类没有复制构造函数,编译器将为您生成一个,它是默认构造函数默认构造函数的行为是逐个成员复制属性,这可能会调用成员的复制构造函数。

std::ofstream不是为复制而设计的,因此它将其复制构造函数标记为已删除,以防止意外复制。 然后,当default构造函数调用std::ofstreamdeleted复制构造函数时,将显示编译错误。

可能的解决方案:

  1. 定义您自己的复制构造函数。 以控制您自己的复制行为。
  2. 或将复制构造函数标记为已删除以防止类被复制,与std::ofstream相同。
  3. 或将您的成员ofs保存为引用类型std::OfStream&,以捕获引用而不是独立实例。 (或std::ofstream*指针)

匿名用户

如果只是因为std::ofstream不可复制而删除test的复制构造函数,为什么要编译呢?

“空”析构函数阻止您的原因是,声明析构函数会抑制move构造函数的隐式生成,因此std::vector::emplace_back必须在向量必须增长的情况下复制test元素。

如果您没有析构函数,那么您将获得使用std::ofstream::ofstream(ofstream&&)的隐式移动构造函数。