C++ 是否修改字符串的长度和内容?

C++ 是否修改字符串的长度和内容?,c++,string,C++,String,要更改函数中字符串的内容,使其反映在主函数中,我们需要接受字符串作为引用,如下所示 但是在上面的代码中,我们也在改变字符串的大小(即,超过它所能容纳的大小),那么为什么程序没有崩溃呢 程序将十进制转换为二进制,请注意,代码不完整,我只是测试代码的第一部分 void dectobin(string & bin, int n) { int i=0; while(n!=0) { bin[i++]= (n % 2) + '0'; n = n /

要更改函数中字符串的内容,使其反映在主函数中,我们需要接受字符串作为引用,如下所示

但是在上面的代码中,我们也在改变字符串的大小(即,超过它所能容纳的大小),那么为什么程序没有崩溃呢

程序将十进制转换为二进制,请注意,代码不完整,我只是测试代码的第一部分

void dectobin(string & bin, int n)
{

  int i=0;

  while(n!=0)
  {
     
     bin[i++]= (n % 2) + '0';
     n = n / 2;
   }

  cout << i << endl;

  cout << bin.size() << endl;

  cout << bin << endl;
}

int main()
{
   string s = "1";
   dectobin(s,55);
   cout << s << endl;
   return 0;
}
void dectobin(字符串和bin,int n)
{
int i=0;
而(n!=0)
{
bin[i++]=(n%2)+“0”;
n=n/2;
}

cout您不会在任何地方更改字符串的大小。如果传入函数的字符串长度为1,并且您在索引大于0的位置访问它,即在
bin[1]
bin[2]
,您不是在修改字符串,而是在字符串之后修改其他一些内存位置-可能还有其他存储位置。以这种方式损坏内存不一定会直接导致崩溃或异常。一旦您稍后在程序中访问这些内存位置,它将立即发生。

检查此关于
std::string
:

如果pos不大于字符串长度,则该函数永远不会 抛出异常(无抛出保证)。否则,将导致 未定义的行为


while
循环中,您正在访问索引大于
bin.size()的
bin
字符串

您的前提是错误的。您认为1)如果我访问一个越界字符串,那么我的程序将崩溃;2)我的程序没有崩溃,因此我不能访问一个越界字符串;3)因此,我显然越界的字符串访问必须实际调整字符串的大小

1) 不正确。访问超出边界的字符串会导致未定义的行为。这正是它所说的。您的程序可能会崩溃,但可能不会,它的行为未定义

事实上,访问字符串永远不会改变它的大小,这就是为什么我们有调整大小的功能(以及向后推等等)


我们每周必须收到几次像您这样的问题。未定义的行为显然是一个让新手感到惊讶的概念。

接受对字符串的引用可以在被调用代码中更改调用代码中的字符串实例:

void access(std::string & str) {
  // str is the same instance as the function
  // is called with.
  // without the reference, a copy would be made,
  // then there would be two distinct instances
}

// ...
std::string input = "test";
access(input);
// ...
因此,在引用上调用的任何函数或运算符都会在引用的实例上有效地调用

与您的链接问题类似,代码

str = " new contents";
位于
access
函数体内部,然后调用
input
实例的
operator=

此(复制分配)运算符将丢弃字符串先前的内容,然后将其参数的字符复制到新分配的存储中,所需的长度在之前确定

另一方面,当您有如下代码时

str[1] = 'a';
access
函数中,这将调用
input
实例上的
operator[]
。此operator只提供对字符串底层存储的访问,不进行任何大小调整

因此,您的问题与引用无关,而是与误用索引
运算符[]
有关:

使用不小于字符串大小/长度的参数调用该运算符会导致未定义的行为

要解决这个问题,可以在使用索引操作符之前手动调整字符串的大小

作为旁注:在我看来,您应该尝试以更实用的方式编写函数:

std::string toOct(std::string const &);

也就是说,不要修改oases字符串,而是创建一个新字符串。

字符串的边界受其当前内容的限制。这就是为什么当您使用6个字符初始化字符串时,您将保持在边界内,以便将55转换为二进制,并且程序运行时不会出错。 字符串的自动扩展功能可以使用 std::string::运算符+= 在当前字符串的末尾追加字符。更改的代码段如下所示:

void dectobin(string & bin, int n){
//...
bin += (n % 2) + '0';
//...
}
另外,您不需要在main()中初始化原始字符串,您的程序现在也可以运行任意小数

int main(){
//...
string s;
dectobin(s,55);
//...
}   

您没有更改字符串的大小。您正在越界访问它。这是未定义的行为。您的代码是不完整的、简单的。请改用
bin+=static_cast((n%2)+“0”);
。[不确定是否需要强制转换。]无论如何,用十进制表示构建一个新字符串,并返回它。不要试图干扰输入。
int main(){
//...
string s;
dectobin(s,55);
//...
}