C++ 更改数据忽略常量限定符

C++ 更改数据忽略常量限定符,c++,pointers,constants,C++,Pointers,Constants,我之前问过一个相关的问题,所以我知道这是一个未定义的行为 string\u str=“SDFDFSD”; char*pStr=(char*)_str.data(); for(int i=0;i

我之前问过一个相关的问题,所以我知道这是一个未定义的行为

string\u str=“SDFDFSD”;
char*pStr=(char*)_str.data();
for(int i=0;i

我和我的一位同事讨论了这个问题。他告诉我,除非我改变数据的长度,否则在这种情况下不会产生任何问题。如果我更改数据但保持长度不变,则不会产生任何问题,因为
std::string
无法检测到数据已更改。它不会在
\u str
中导致任何内部不一致。真的是这样吗?

坏主意!您无法确定string是如何在任何当前或将来的平台上实现的。例如,它可以与其他类似的对象共享存储。在某些平台上,可能将数据放在只读段中。

根据文档:

修改通过数据访问的字符数组是未定义的行为

所以你的同事是错的,没有诡计,这是未定义的行为。所发生的事情是特定于实现的。

我担心,对未定义行为的谴责太多了,对鼻守护进程的引用似乎让大多数人相信它比其他任何东西都更神秘

似乎你的同事已经变得如此麻木,为了说服你,因此需要给他带来这个问题的具体证据。幸运的是,如果您手头有gcc,则可以:

#include <iostream>
#include <string>

int main() {
    std::string const UPPER = "HELLO, WORLD!";
    std::cout << "UPPER: " << UPPER << "\n";

    std::string lower = UPPER;
    for (char* begin = const_cast<char*>(lower.data()),
         * end = begin + lower.size();
         begin != end;
         ++begin)
    {
        *begin = std::tolower(*begin);
    }
    std::cout << "lower: " << lower << "\n";
    std::cout << "UPPER: " << UPPER << "\n";
    return 0;
}
为什么??因为gcc历史上一直使用写时拷贝,而且由于您作弊,它没有检测到写操作,因此底层存储阵列是共享的


注意:是的,这不符合C++11,但我希望我有机会在C++11中工作。

这是UB,因此允许实现执行它喜欢的任何操作。带有UB的程序是一个坏程序。在本例中,C++11之前的实现允许对字符串使用写时复制(COW)。那会引起一个问题。还要注意的是,即使没有COW.Just,它也会导致假定const正确性的字符串用户出现问题。。不要。是UB。时期如果要将标准容器视为可变的c-ctyle字符串,请使用背面带有终止符的
std::vector
。是的,您丢失了
std::string
的所有kewl-whiz-bang功能,但您似乎并不想使用它们。样本使用率很低,因为这很容易通过定义的行为来实现,例如,
std::for_each
std::transform
for(auto&x:…
)等。保持定义的行为;总是。是的,我知道这是一种未定义的行为,不应该这样做。我真正想知道的是,在回答中提到的
中,类似于DrC的东西可能是与其他类似的对象共享存储。在某些平台上,可能是将数据放在只读段中。
这意味着在这些情况下,
\u str
内部将存在不一致性。如果数据放在只读段中,完全没有不一致性,它将崩溃。
#include <iostream>
#include <string>

int main() {
    std::string const UPPER = "HELLO, WORLD!";
    std::cout << "UPPER: " << UPPER << "\n";

    std::string lower = UPPER;
    for (char* begin = const_cast<char*>(lower.data()),
         * end = begin + lower.size();
         begin != end;
         ++begin)
    {
        *begin = std::tolower(*begin);
    }
    std::cout << "lower: " << lower << "\n";
    std::cout << "UPPER: " << UPPER << "\n";
    return 0;
}
UPPER: HELLO, WORLD!
lower: hello, world!
UPPER: hello, world!   // What the hell ? UPPER was const !!!