为什么cout << * s << endl会产生段错误?

时间:2019-05-03 01:25:23

标签: c++

我在C ++类的实践考试中有这个问题,我们应该写输出是什么,或者它是否产生错误。运行此代码会产生分段错误,但有人可以解释原因吗?对我来说很好。

    string *s;
    s = (string *) "This is my house. I have to defend it.";
    cout << *s << endl;

4 个答案:

答案 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和中的内存位置结束都是胡说八道)