【问题标题】:Const std::filesystem::path reference constness is not respected, is this something I did wrong?不尊重 const std::filesystem::path 引用常量,这是我做错了什么吗?
【发布时间】:2021-08-24 15:33:06
【问题描述】:

我正在处理一个文件遍历项目,并且我想跟踪正在检查的当前项目,所以我有一个外部 filesystem::path CurrentItem 值,我在遍历的每个级别/步骤上都会更改以跟上日期。

我正在使用一个递归函数,该函数采用const filesystem::path& 遍历文件,const path 引用而不是path 本身,因此我可以避免字符串复制开销。我知道在事情的规模上,这可能不是这个程序中最繁重的操作,但这是我选择做的。

当遍历循环的入口深度时,当我用循环的directory_entry 的路径更新CurrentItem 路径时,函数参数path 也以某种方式被设置。这让我感到莫名其妙,特别是考虑到添加一个手表它告诉我,即使是底层的wstring 也被标记为const,所以我很茫然。

底线,我想知道我是否以某种方式做错了足以破坏const,或者它实际上是一个我只需要解决的错误。我可以只创建一个辅助path 来分配输入值,这与const 参数没有相同的问题,或者我可以将参数更改为普通const path,但这两者都是解决方案重新引入了我想避免的额外不必要的副本。

我在一个完全干净的环境中将代码从我的项目中分离出来,它表现出完全相同的行为。

我复制了所有外部变量,减去类封装。我在 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
    }
}

【问题讨论】:

  • 寻找副本。简短的回答:您的 const 引用适用于 变量,而不是 object

标签: c++ windows c++17 boost-filesystem


【解决方案1】:

当您使用可修改的全局变量时会发生这种情况。

thisPath 引用的对象不能被thisPath 变量修改,但是如果有其他方法可以访问该对象,那么它可以采用不同的值。例如,如果它是对全局变量的引用,如果你修改了那个全局变量,那么被引用的对象已经改变了。

当然,您的HandleFilesInDirectory 函数使用CurrentItem 调用自身。这意味着对该函数的递归调用将获得对可修改全局变量的引用。然后在函数中修改一个全局变量。

const&amp; 只是防止通过该变量修改。如果对象可以通过其他方式修改,const&amp; 将看到这些修改。

【讨论】:

  • 啊,非常感谢!我忘了考虑我使用 CurrentItem 作为我传入的参考
  • 现在很容易通过 entry.path() 进行返工,并且可以完美运行
猜你喜欢
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多