c ++在编写公共变量时崩溃了

Rog*_*Far 0 c++

我用c ++编写了一个简单的测试程序,但为什么会崩溃:

s[i] = s[i] - 'a' + 'A';
Run Code Online (Sandbox Code Playgroud)

例外:访问冲突写入位置0x01327808

#include "stdafx.h"
#include <iostream>

using namespace std;

class String
{
public:
  char *s;
  int len();
  void upper();

  String(char*);

};

String::String(char*x)
{
  s = x;
}

int String::len()
{
  return strlen(s);
}

void String::upper()
{
  for (int i = 0; i < len(); i++)
  {
    if (s[i] >= 'a' && s[i] <= 'z')
    {
      cout << s[i] << endl;
      s[i] = s[i] - 'a' + 'A';
    }
  }
};

int main()
{
  String s("test");
  s.upper();

  cout << s.len() << endl;
  cout << s.s << endl;

  system("pause");
}
Run Code Online (Sandbox Code Playgroud)

pax*_*blo 10

这是因为:

String s("test");
Run Code Online (Sandbox Code Playgroud)

这样做是为了传递const char * "test"给你的构造函数,然后只是存储该字符串的地址.

稍后,当您尝试修改指针指向的内存时,这是未定义的行为.

通常,字符串文字将存储在只读内存中以允许进行某些优化,并且任何修改它们的尝试都将导致访问冲突.

如果你要改变:

String s("test");
Run Code Online (Sandbox Code Playgroud)

成:

char cp[] = "test";
String s(cp);
Run Code Online (Sandbox Code Playgroud)

你可能会发现它会起作用.

但是,你的类应该真正为它自己的目的制作一个字符串的副本 - 仅仅指针是不安全的,因为传递给你指针的代码也可以改变它的内容.

您应该在代码中更改的内容,以使其更安全:

  • s 应该是私人会员,而不是公共会员.
  • 你的构造函数应该创建自己的字符串副本:
    s = new char[strlen(x)+1];
    strcpy (s,x);.
  • 添加一个析构函数来照顾这也:
    String::~String() { delete[] s; }.
  • 考虑让你的构造函数接收一个const char *(因为你没有改变它).
  • 考虑使用toupper(ch)而不是ch - 'a' + 'A'.虽然您的公式适用于ASCII,但我不相信它符合标准.
  • cout应该由类处理,而不是在它之外的代码处理(一旦你s私有,这将是强制性的.
  • 考虑使用无参数构造函数,以便字符串数组可以正常工作.

  • @Rogier21:如果你还没有,你迫切需要阅读一本关于C++的书.与其他一些语言不同,你不能通过猜测来编写有效的C++代码. (4认同)