今天在编译项目时,代码审查提示 “Single-parameter constructors should be marked explicit”
于是就在构造函数前加上 explicit
下面为最小的示例,这个示例主要是按文件创建时间排序并删除过期的文件
#include <iostream>
#include <thread>
#include <windows.h>
#include <exception>
#include <vector>
#include <filesystem>
wchar_t file_path[] =
L"D:/VS2019_Program/Test_SetUnhandledExceptionFilter/Debug/.sentry-native/reports/";
wchar_t file_ext[] = L".dmp";
std::vector<std::wstring> TraverseFolder(std::wstring folder_path,
std::wstring ext);
class file {
public:
std::wstring name;
FILETIME time;
public:
bool operator<(file const& other) const {
return CompareFileTime(&other.time, &time) == 1;
}
file(WIN32_FIND_DATA const &d) : name(d.cFileName), time(d.ftCreationTime) {}
};
std::vector<file> SortDumpFiles(std::vector<std::wstring> dumpfiles) {
std::vector<file> files;
std::transform(dumpfiles.begin(), dumpfiles.end(), std::back_inserter(files),
[](std::wstring const &fname) {
WIN32_FIND_DATA d;
HANDLE h = FindFirstFile(fname.c_str(), &d);
FindClose(h);
return d;
});
std::sort(files.begin(), files.end());
return files;
}
void DelExpiredDumpFiles() {
std::wstring path(file_path);
std::wstring ext(file_ext);
auto dump_file = TraverseFolder(path, ext);
int total_file = dump_file.size();
int to_be_deleted = total_file - 4;
if (to_be_deleted <= 0) {
return;
}
// 以文件创建时间
auto files = SortDumpFiles(dump_file);
while (to_be_deleted--) {
std::wstring file = file_path;
file += files[to_be_deleted].name;
if (!DeleteFile(file.c_str())) {
int err = GetLastError();
return;
}
}
}
std::vector<std::wstring> TraverseFolder(std::wstring folder_path,
std::wstring ext) {
std::vector<std::wstring> filename;
if (!std::filesystem::is_directory(folder_path)) {
return filename;
}
for (auto& p : std::filesystem::recursive_directory_iterator(folder_path)) {
if (p.path().extension() == ext) {
filename.push_back(p.path().wstring());
}
}
return filename;
}
int main() {
DelExpiredDumpFiles();
return 0;
}
添加 explicit 关键词
explicit file(WIN32_FIND_DATA const &d) : name(d.cFileName), time(d.ftCreationTime) {}
编译会报错,
解决方法,
std::transform(dumpfiles.begin(), dumpfiles.end(), std::back_inserter(files),
[](std::wstring const &fname) {
WIN32_FIND_DATA d;
HANDLE h = FindFirstFile(fname.c_str(), &d);
FindClose(h);
return file{d};
});
原因:
explicit 关键字
- 指定构造函数或转换函数 (C++11起)为显式, 即它不能用于隐式转换和复制初始化.
- explicit 指定符可以与常量表达式一同使用. 函数若且唯若该常量表达式求值为 true 才为显式. (C++20起)
也就是构造函数被 explicit 修饰后, 就不能再被隐式调用了
等于说,std::vector<file> files = d 这样的操作禁止使用了,只能 std::vector<file> files = files{d}
Effective C++中也阐述了:
被声明为explicit
的构造函数通常比其 non-explicit 兄弟更受欢迎, 因为它们禁止编译器执行非预期 (往往也不被期望) 的类型转换. 除非我有一个好理由允许构造函数被用于隐式类型转换, 否则我会把它声明为explicit
. 我鼓励你遵循相同的政策.