std::cout &operator<< 的奇怪行为
我今天遇到了一些奇怪的事情,我想知道这里的任何人是否可以解释发生了什么......
这是一个示例:
#include <iostream>
#include <cassert>
using namespace std;
#define REQUIRE_STRING(s) assert(s != 0)
#define REQUIRE_STRING_LEN(s, n) assert(s != 0 || n == 0)
class String {
public:
String(const char *str, size_t len) : __data(__construct(str, len)), __len(len) {}
~String() { __destroy(__data); }
const char *toString() const {
return const_cast<const char *>(__data);
}
String &toUpper() {
REQUIRE_STRING_LEN(__data, __len);
char *it = __data;
while(it < __data + __len) {
if(*it >= 'a' && *it <= 'z')
*it -= 32;
++it;
}
return *this;
}
String &toLower() {
REQUIRE_STRING_LEN(__data, __len);
char *it = __data;
while(it < __data + __len) {
if(*it >= 'A' && *it <= 'Z')
*it += 32;
++it;
}
return *this;
}
private:
char *__data;
size_t __len;
protected:
static char *__construct(const char *str, size_t len) {
REQUIRE_STRING_LEN(str, len);
char *data = new char[len];
std::copy(str, str + len, data);
return data;
}
static void __destroy(char *data) {
REQUIRE_STRING(data);
delete[] data;
}
};
int main() {
String s("Hello world!", __builtin_strlen("Hello world!"));
cout << s.toLower().toString() << endl;
cout << s.toUpper().toString() << endl;
cout << s.toLower().toString() << endl << s.toUpper().toString() << endl;
return 0;
}
现在,我预计输出是:
hello world!
HELLO WORLD!
hello world!
HELLO WORLD!
但我得到的是:
hello world!
HELLO WORLD!
hello world!
hello world!
我真的无法理解为什么第二个 toUpper
没有任何效果。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这都是因为您的代码
以及
toLower
和toUpper
的实现方式。以下代码应该按预期工作问题是
toLower
和toUpper
不会创建新对象,而是修改现有对象。当您在同一个块中调用多个修改方法并将该对象作为参数传递到某处时,行为是未定义的。编辑:这类似于流行的问题,这会是什么结果
这里的正确答案是相同的:未定义。您可以在 C++ 中搜索“序列点”以获得更深入的解释。
This is all because of your code
and how
toLower
andtoUpper
are implemented. Following code should work as expectedThe issue is that
toLower
andtoUpper
don't create a new object but modify existing object. And when you call several modifying methods in the same block AND pass this object somewhere as argument, behavior is undefined.EDIT: This is similar to popular question, what would be result of
The correct answer here is the same: undefined. You can google for "sequence points" in C++ for deeper explanation.