C++ 使用`const\u cast<;将`std::string::c_str()`的结果传递给`mkdtemp()`;字符*>;()`

C++ 使用`const\u cast<;将`std::string::c_str()`的结果传递给`mkdtemp()`;字符*>;()`,c++,stdstring,mutable,c-strings,const-cast,C++,Stdstring,Mutable,C Strings,Const Cast,好吧,那么:我们都知道,通常在任何地方使用const_cast()都是非常糟糕的,这实际上是一种编程战争罪。所以这是一个假设性的问题,关于在一个特定的案例中,它到底有多糟糕 也就是说:我遇到了一些代码,它们做了如下操作: std::string temporary = "/tmp/directory-XXXXX"; const char* dtemp = ::mkdtemp(const_cast<char*>(temporary.c_str())); /// `temporary`

好吧,那么:我们都知道,通常在任何地方使用
const_cast()
都是非常糟糕的,这实际上是一种编程战争罪。所以这是一个假设性的问题,关于在一个特定的案例中,它到底有多糟糕

也就是说:我遇到了一些代码,它们做了如下操作:

std::string temporary = "/tmp/directory-XXXXX";
const char* dtemp = ::mkdtemp(const_cast<char*>(temporary.c_str()));
/// `temporary` is unused hereafter
std::string temporary=“/tmp/directory-XXXXX”;
const char*dtemp=::mkdtemp(const_cast(temporary.c_str());
///‘temporary’以后不用了

……现在,我已经遇到了许多关于如何获得可访问的“代码> STD::String < /Calp>实例(例如Q.V)的底层缓冲区的描述),他们都有一个警告:是的,这些方法不能保证任何C++标准都能工作,但实际上它们都是这样做的。p> 考虑到这一点,我只是好奇使用

const_cast(string.c_str())
与其他已知方法(例如前面提到的
&string[0]
,&c)相比如何。我问这个问题是因为我发现使用此方法的代码在实践中似乎运行良好,我想在我尝试不可避免的
const\u cast()
免费重写之前,我会看看专家们的想法。

  • const
    不能在硬件级别强制执行,因为实际上,在非假设性环境中,您可以将只读属性仅设置为完整的4K内存页,并且在执行过程中会有大量页面,这大大减少了CPU在内存中的查找失误

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

由于
std::string
是一个可变字符串,因此无法在只读内存中分配其底层缓冲区。所以
const\u cast
不应该在这里导致程序崩溃,除非您要更改底层缓冲区边界之外的一些字节,或者尝试
删除
free()
realloc()
什么。然而,改变缓冲区中的字符可能被归类为不变冲突。因为在此之后不使用
std::string
实例并简单地将其扔掉,所以这不会引发程序崩溃,除非某个特定的
std::string
实现决定在销毁之前检查其不变量的完整性,并在其中一些不变量被破坏时强制崩溃。因为这样的检查不能在少于O(N)的时间内完成,而且
std::string
是一个性能关键类,所以任何人都不可能完成


另一个问题可能来自战略。因此,通过直接修改缓冲区,您可能会破坏其他与字符串共享缓冲区的
std::string
实例。但是几年前,大多数C++专家得出结论,牛是太脆弱和太慢,特别是在多线程环境中,所以现代的C++库不应该使用它,而是坚持尽可能使用移动构造,并且避免适用于小长度字符串的堆流量。p> 使用
std::vector
代替
std::string
。你有一个可写的缓冲区,没有所有的强制转换。这不是我要问的——我可以想出很多方法来做,但没有问题。我很好奇问题的本质。顺便说一句:正确的实现应该是:
char temporary[]=“/tmp/directory-XXXXX”;char*dtemp=mkdtemp(临时)
由于这会在堆栈上创建一个数组,该数组由字符串文本的副本初始化,因此您有权修改该副本,包括将其传递给
mkdtemp()
。确实,这里没有闪亮的C++素材,但它比你所浏览的版本更短、更简单、更正确:-@ cMead绝对是的——虽然它更简洁,更不迂回,但是我发布的代码是对实际生产代码的过度简化。这自然是混乱的,足以使这样一个简单的编辑是可行的。但是您确实正确地将静态赋值给基于可写堆栈的临时对象,作为
mkdtemp()
使用的理想素材。我认为这有点误导。不允许丢弃
常量
,然后通过该指针写入缓冲区。你只能阅读。要获得对字符串内容的写访问权限,请使用
&s[0]
@fish2000。它会导致未定义的行为,其中可能包括显示为按预期工作。或者换句话说,编译器可能支持也可能不支持它(如果不支持,您不会得到任何警告)a)
const
不能在硬件级别强制执行b)
const
不会像C99那样影响代码生成。事实上,
const
,粗略地说,意思是“毒害所有对这些东西的写入尝试,这有望保护我的不变量”。关于检查析构函数中的不变量:
std::string::size()
被定义为具有
O(1)
复杂性,因此,所有实现都需要保持字符串的大小或指向字符串末尾的指针。这些信息足以在固定时间内对字符串末尾的空字节进行健全性检查。因此,如果终止字节被覆盖,实现可能会强制崩溃。@fish2000我是这样看的:尾随的
NUL
字节由实现隐式地放在那里,不能由合法的用户代码删除。因此,如果
NUL
字节被覆盖,则程序已进入UB。在这种情况下,中止该过程是一种完全允许的操作过程,而且检查成本很低。没错,这是语言律师的观点,但我得出的结论是,在UB问题上,最好听听语言律师的意见。有太多的情况下,化学需氧量