gpt4 book ai didi

c++ - 什么在引用复制构造函数?

转载 作者:行者123 更新时间:2023-12-01 14:18:12 27 4
gpt4 key购买 nike

根据我构建 Log 对象的方式,我收到一个编译器错误,指出我正在尝试引用已删除的函数(复制构造函数):

C:\Projects\Logger\src\Logger.cpp(34,1): error C2280: 'Logger::Log::Log(const Logger::Log &)': attempting to reference a deleted function [C:\Projects\Logger\build\Logger.vcxproj]

我的 Log 对象应该有 implicitly deleted复制构造函数,因为:

T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);

这是有道理的,因为 std::ofstream 有它的 copy constructor deleted .

我不明白为什么要调用复制构造函数。使用调用复制构造函数的赋值运算符进行构造有何意义?我正在使用 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;
}

类接口(interface)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;

I got this error E1776 function "std::basic_ofstream<_Elem, _Traits>::operator=(const std::basic_ofstream<_Elem, _Traits> &) [with _Elem=char, _Traits=std::char_traits]" (declared at line 1080 of "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.25.28610\include\fstream") cannot be referenced -- it is a deleted function

这意味着 ofstream 阻止复制构造函数和 =operator 以避免访问相同的数据(文件),当您通过此行调用复制构造函数时,您的代码就是这种情况

 Logger::Log foo = Logger::Log::Log("sample.log");

隐式使用默认复制构造函数,它使用 =operator 为您拥有的每个对象或原始类型逐个字段复制,这就是 ofstream 的情况,它阻止 =operator 然后编译器标记为调用已删除的函数错误--

to solve this you can declare ofstream pointer using raw pointers or smart ones and manage the memory or you can also create your move constructor version with your customization --which will delete the default copy constructor in your class also-- and try to avoid the access to the same data using different ofstreams.

关于c++ - 什么在引用复制构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63275405/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com