const std::filesystem::path reference constness 不被尊重,这是我做错了什么吗?
Const std::filesystem::path reference constness is not respected, is this something I did wrong?
我正在处理一个文件遍历项目,我想跟踪当前正在检查的项目,所以我有一个外部 filesystem::path CurrentItem
值,我会在每个 level/step 上更改它遍历以保持最新。
我正在使用一个递归函数,该函数采用 const filesystem::path&
来遍历文件,const path
引用而不是 path
本身,因此我可以避免字符串复制开销.我知道从事情的规模来看,它可能不是这个程序中最繁重的操作,但这是我选择做的。
当遍历超出循环的入口深度时,当我用循环的 directory_entry
路径更新 CurrentItem
路径时,函数参数 path
也以某种方式设置.这让我感到莫名其妙,尤其是考虑到添加手表时它向我展示了即使底层 wstring
也被标记为 const
,所以我不知所措。
最重要的是,我想知道我是否做错了足以破坏 const
的事情,或者它是否真的是一个我只需要解决的错误。我可以只创建一个辅助 path
并将输入值分配给它,并且它与 const
参数没有相同的问题,或者我可以将参数更改为普通的 const path
,但这两种解决方案都重新引入了我想避免的额外不必要的副本。
我在一个完全干净的环境中将代码从我的项目中分离出来,它表现出完全相同的行为。
我按原样复制了所有外部变量,减去 class 封装。我在 windows 10 上的 VS19 中 运行,在 32 位和 64 位上进行了测试,同样的情况发生了。这是:
#include <iostream>
#include <filesystem>
using namespace std::filesystem;
std::error_code ec;
path StartDirectory = L"D:/Camera Import/Animals/RAW";
path CurrentItem;
bool Recursive = true;
bool DoFiles = false;
bool DoFolders = true;
void HandleFilesInDirectory(const path& thisPath);
int main()
{
std::cout << "Hello World!\n";
StartDirectory.make_preferred();
CurrentItem = StartDirectory;
if (is_directory(StartDirectory, ec))
{
HandleFilesInDirectory(StartDirectory);
}
}
void HandleFilesInDirectory(const path& thisPath)
{
for (const directory_entry& entry : directory_iterator(thisPath))
{
auto type = entry.status().type();
// This assignment operation causes the const path& thisPath to be reassigned somehow,
// despite it being const and also being unrelated to the items in the assignment
CurrentItem = entry.path();
if (entry.is_directory(ec))
{
if (Recursive)
{
HandleFilesInDirectory(CurrentItem);
}
if (DoFolders)
{
// Do project-specific operations
}
}
else if (DoFiles && entry.is_regular_file(ec))
{
// Do project-specific operations
}
}
CurrentItem = thisPath;
if (!thisPath.compare(StartDirectory))
{
// Do project-specific operations
}
}
当您使用可修改的全局变量时会发生这种情况。
thisPath
引用的对象不能由 thisPath
变量修改,但如果有另一种方法访问该对象,则它可以采用不同的值。比如它是一个全局变量的引用,如果你修改了那个全局变量,那么引用的对象就被改变了。
当然,您的 HandleFilesInDirectory
函数使用 CurrentItem
调用自身。这意味着对该函数的递归调用将被赋予对可修改全局变量的引用。然后在函数内修改的全局变量。
const&
只是对通过该变量 修改 的保护措施。如果对象可以其他方式修改,const&
将看到这些修改。
我正在处理一个文件遍历项目,我想跟踪当前正在检查的项目,所以我有一个外部 filesystem::path CurrentItem
值,我会在每个 level/step 上更改它遍历以保持最新。
我正在使用一个递归函数,该函数采用 const filesystem::path&
来遍历文件,const path
引用而不是 path
本身,因此我可以避免字符串复制开销.我知道从事情的规模来看,它可能不是这个程序中最繁重的操作,但这是我选择做的。
当遍历超出循环的入口深度时,当我用循环的 directory_entry
路径更新 CurrentItem
路径时,函数参数 path
也以某种方式设置.这让我感到莫名其妙,尤其是考虑到添加手表时它向我展示了即使底层 wstring
也被标记为 const
,所以我不知所措。
最重要的是,我想知道我是否做错了足以破坏 const
的事情,或者它是否真的是一个我只需要解决的错误。我可以只创建一个辅助 path
并将输入值分配给它,并且它与 const
参数没有相同的问题,或者我可以将参数更改为普通的 const path
,但这两种解决方案都重新引入了我想避免的额外不必要的副本。
我在一个完全干净的环境中将代码从我的项目中分离出来,它表现出完全相同的行为。
我按原样复制了所有外部变量,减去 class 封装。我在 windows 10 上的 VS19 中 运行,在 32 位和 64 位上进行了测试,同样的情况发生了。这是:
#include <iostream>
#include <filesystem>
using namespace std::filesystem;
std::error_code ec;
path StartDirectory = L"D:/Camera Import/Animals/RAW";
path CurrentItem;
bool Recursive = true;
bool DoFiles = false;
bool DoFolders = true;
void HandleFilesInDirectory(const path& thisPath);
int main()
{
std::cout << "Hello World!\n";
StartDirectory.make_preferred();
CurrentItem = StartDirectory;
if (is_directory(StartDirectory, ec))
{
HandleFilesInDirectory(StartDirectory);
}
}
void HandleFilesInDirectory(const path& thisPath)
{
for (const directory_entry& entry : directory_iterator(thisPath))
{
auto type = entry.status().type();
// This assignment operation causes the const path& thisPath to be reassigned somehow,
// despite it being const and also being unrelated to the items in the assignment
CurrentItem = entry.path();
if (entry.is_directory(ec))
{
if (Recursive)
{
HandleFilesInDirectory(CurrentItem);
}
if (DoFolders)
{
// Do project-specific operations
}
}
else if (DoFiles && entry.is_regular_file(ec))
{
// Do project-specific operations
}
}
CurrentItem = thisPath;
if (!thisPath.compare(StartDirectory))
{
// Do project-specific operations
}
}
当您使用可修改的全局变量时会发生这种情况。
thisPath
引用的对象不能由 thisPath
变量修改,但如果有另一种方法访问该对象,则它可以采用不同的值。比如它是一个全局变量的引用,如果你修改了那个全局变量,那么引用的对象就被改变了。
当然,您的 HandleFilesInDirectory
函数使用 CurrentItem
调用自身。这意味着对该函数的递归调用将被赋予对可修改全局变量的引用。然后在函数内修改的全局变量。
const&
只是对通过该变量 修改 的保护措施。如果对象可以其他方式修改,const&
将看到这些修改。