使用 'const_cast<char*>()' 将 'std::string::c_str()' 的结果传递给 'mkdtemp()'

Passing the results of `std::string::c_str()` to `mkdtemp()` using `const_cast<char*>()`

本文关键字:结果 str mkdtemp string const char lt gt 使用 std cast      更新时间:2023-10-16

好吧,所以:我们都知道,通常在任何地方使用const_cast<>()都很糟糕,这实际上是一种编程战争罪。因此,这是一个关于在特定情况下可能有多糟糕的假设问题。

也就是说:我遇到了一些代码,它做了这样的事情:

std::string temporary = "/tmp/directory-XXXXX";
const char* dtemp = ::mkdtemp(const_cast<char*>(temporary.c_str()));
/// `temporary` is unused hereafter

……现在,我已经看到了许多关于如何对std::string实例的底层缓冲区进行可写访问的描述(q.v。https://stackoverflow.com/a/15863513/298171例如)–所有这些方法都有一个警告,是的,这些方法不能保证任何C++标准都能工作,但在实践中它们都能工作。

考虑到这一点,我只是想知道使用const_cast<char*>(string.c_str())与其他已知方法(例如前面提到的&string[0],&c)相比如何……我之所以这么问,是因为我发现使用这种方法的代码在实践中似乎运行良好,我想在尝试不可避免的无const_cast<>()重写之前,我会看看专家们的想法。

  • const不能在硬件级别强制执行,因为在实践中,在非假设环境中,您可以仅将只读属性设置为完整的4K内存页,并且有大量页面正在进行中,这大大减少了CPU在TLB中的查找未命中。

  • const不会像C99中的__restrict那样影响代码生成。事实上,const,粗略地说,意思是"毒害所有对此数据的写入尝试,我想在这里保护我的不变量"

由于std::string是一个可变字符串,其底层缓冲区不能在只读内存中分配。所以const_cast<>不应该导致程序崩溃,除非您要更改一些超出底层缓冲区界限的字节,或者尝试deletefree()realloc()之类的字节。然而,改变缓冲区中的字符可能被归类为不变违反。因为在那之后不使用std::string实例,只需将其丢弃,所以这不应该引发程序崩溃,除非某个特定的std::string实现决定在销毁之前检查其不变量的完整性,并在其中一些不变量损坏时强制崩溃。因为这样的检查不可能在小于O(N)的时间内完成,而且std::string是性能关键类,所以任何人都不太可能完成。

另一个问题可能来自写时复制策略。因此,通过直接修改缓冲区,您可以破坏与您的字符串共享缓冲区的其他std::string的实例。但几年前,大多数C++专家得出结论,COW太脆弱、太慢,尤其是在多线程环境中,所以现代C++库不应该使用它,而是坚持在可能的情况下使用移动构造,并在适用的情况下避免小长度字符串的堆流量。