我在C ++类的实践考试中有这个问题,我们应该写输出是什么,或者它是否产生错误。运行此代码会产生分段错误,但有人可以解释原因吗?对我来说很好。
string *s;
s = (string *) "This is my house. I have to defend it.";
cout << *s << endl;
答案 0 :(得分:4)
在类型std::string*
的指针未指向类型为std::string
的对象时进行间接调用具有不确定的行为。
字符串文字不是std::string
类型的对象。字符串文字是字符数组。 std::string
是在标题<string>
中定义的类。
运行此代码会产生细分错误,但有人可以解释原因吗?
您通过不指向兼容类型对象的指针进行间接操作。您的程序的行为是不确定的。
P.S。永远不需要使用C样式的强制类型转换(例如(type)expression
)。它可以轻松地抑制有用的编译错误并将其替换为未定义的行为。应该避免。
如果您在这里没有使用C风格的转换,那么类型系统会在开始运行该程序之前警告您该错误。在这种情况下,您可能会看到类似于以下内容的错误消息:
error: cannot convert 'const char [39]' to 'std::string*' {aka 'std::basic_string<char>*'} in assignment
帮助您意识到类型不匹配。
答案 1 :(得分:1)
您需要学习string literal和课程std::string
之间的区别。
将字符串文字投射到std::string*
是未定义的行为。当代码执行*s
时,由于s
无效,这在这里表现为分段错误。
如果没有(string *)
中的C样式强制转换s = (string *) "T...";
,编译器将发出错误。
总是质疑C ++中的那些C样式强制转换。
答案 2 :(得分:0)
可能的问题(或至少一个问题)是s没有分配内存的事实。您需要使用new关键字,然后尝试执行以下操作:
string *s;
s = new string("This is my house. I have to defend it.");
cout << *s << endl;
当然,从理论上讲,您也需要使用Delete。
答案 3 :(得分:-1)
std :: string往往会归结为以下形式:
struct string
{
char* _begin;
char* _end;
char* _capacity;
};
您定义的文本字符串如下所示:
const char* const text = "This is my house. I have to defend it."
因此,您正在从类型(char *)转换为类型(string *)。现在,这意味着_begin将存储内存位置“这是” ,并且_end将存储内存位置“我的房子”
在将字符串打印到std :: cout时,它将取消指向s的指针,并尝试查找字符串大小,通常这样实现:
size_t string::size() const { return _end - _begin; }
鉴于_begin和_end没有存储指针值(它们只是文本的随机位),这将导致cout尝试打印错误数量的字符_(因为_begin和中的内存位置结束都是胡说八道)