根据构造Log
对象的方式,我收到一个编译器错误,指出我正在尝试引用一个已删除的函数(复制构造函数):
C:\ Projects \ Logger \ src \ Logger.cpp(34,1):错误C2280:“ Logger :: Log :: Log(const Logger :: Log&)”:尝试引用已删除的函数[C:\ Projects \ Logger \ build \ Logger.vcxproj]
预计我的Log对象已隐式删除了复制构造函数,因为:
T具有无法复制的非静态数据成员(已删除,不可访问或模棱两可的复制构造函数);
这是有道理的,因为删除了std::ofstream
它的副本构造函数。
我不明白的是为什么根本要调用复制构造函数。用赋值运算符调用复制构造函数进行构造有什么用?我正在使用MSVC进行编译,是否有一些我未使用的编译器标志无法优化某些行为?例如,构造临时对象,然后将构造复制到命名对象中foo
?
如下面的代码块所示,只有一个构造函数定义。
#include <iostream>
#include <string>
#include <fstream>
#include "Logger.h"
#include "LoggerConfig.h"
Logger::Log::Log(std::string file) : filename{ file }
{
logFile = std::ofstream(filename, std::ios::out);
if (logFile.is_open())
{
logFile << "This is a log.\n";
}
else
{
std::cout << "Unable to open filename: " << filename << '\n';
}
}
Logger::Log::~Log()
{
// Wait and take write mutex
// Close file
}
int main()
{
// report version
std::cout << " Version " << LOGGER_VERSION_MAJOR << "."
<< LOGGER_VERSION_MINOR << std::endl;
Logger::Log foo = Logger::Log::Log("sample.log"); // C2280: attemping to reference a deleted function
//Logger::Log foo("sample.log"); // Works!
//Logger::Log foo{"sample.log"}; // Works!
foo.Write(Logger::Log::Level::INFO, "Testing", 123, "hahaha");
return 0;
}
类接口logger.h如下:
#pragma once
namespace Logger
{
class Log
{
private:
std::string filename;
std::ofstream logFile;
public:
enum class Level
{
DEBUG,
INFO,
WARNING,
ERROR
};
Log(std::string file);
~Log();
template<typename T>
void Write(Level lvl, T arg)
{
logFile << arg;
return;
}
template<typename T, typename... Args>
void Write(Level lvl, T firstArg, Args... args)
{
logFile << firstArg;
Write(lvl, args...);
return;
}
};
}
不仅仅涉及不必要的副本和C ++ 17,我们知道
Logger::Log foo("sample.log");
正常工作,但为什么这标志C2280错误
Logger::Log foo = Logger::Log::Log("sample.log");
问题出在类中的ofstream中,我得到了您的代码,并对其进行了编译,我对ofstream对象有疑问,我删除了它,并且它也能正常工作,我使它的指针也能正常工作,然后我尝试了码:
std::ofstream s = std::ofstream("sample.log", std::ios::out);
std::ofstream k;
k = s;
我收到此错误E1776函数“ std :: basic_ofstream <_Elem,_Traits> :: operator =(const std :: basic_ofstream <_Elem,_Traits>&)[with _Elem = char,_Traits = std :: char_traits]”(声明为不能引用“ C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Enterprise \ VC \ Tools \ MSVC \ 14.25.28610 \ include \ fstream”的行1080-这是一个已删除的函数
这意味着流阻止复制构造函数和= operator避免访问相同的数据(文件),当您通过此行调用复制构造函数时,代码中就是这种情况
Logger::Log foo = Logger::Log::Log("sample.log");
隐式地使用默认的复制构造函数,它对每个拥有的对象或原始类型使用= operator逐字段复制,这是ofstream的情况,它防止= operator然后编译器通过调用已删除的函数错误进行标记-
要解决此问题,您可以使用原始指针或智能指针声明ofstream指针并管理内存,也可以使用自定义创建move构造函数版本-这也会删除类中的默认复制构造函数-并尝试避免使用不同的流访问相同的数据。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句