为什么必须指向char数组的指针需要strcpy来为其数组赋值,双引号赋值不起作用?

Oma*_*mar 10 c++ arrays string char strcpy

当你去删除指针时,第一个例子不起作用.当我添加null终止符时,程序要么挂起,要么没有它我得到:

Debug Assertion Failed Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) 来自Visual Studio 2008

//Won't work when deleting pointer:
    char *at = new char [3];
    at = "tw"; //   <-- not sure what's going on here that strcpy does differently
    at[2] = '\0'; // <-- causes program to hang
    delete at;

//Works fine when deleting pointer:
    char *at = new char [3];
    strcpy(at,"t");
    at[1] = 'w';
    at[2] = '\0';
    delete at;
Run Code Online (Sandbox Code Playgroud)

那么当我使用双引号而不是strcpy时会发生什么?它们都会完美地完成字符串,调试器不会显示任何不同的内容.

unw*_*ind 14

当你这样做

char *at = ...;

at = "hello";
Run Code Online (Sandbox Code Playgroud)

您基本上用new[]静态常量字符串的地址覆盖指针值(即,为您分配的内存的地址).这意味着当您稍后删除内存时,您将传递delete之前未返回的指针new.

这是一件坏事.

在C和C++中,对指针的赋值通常不会对指向的内存执行任何操作,它们会更改指针本身.如果你习惯于字符串更像是"一等公民"的语言,这可能会让人感到困惑.

此外,delete[]如果您使用,您应该使用new[].


sbi*_*sbi 12

因为a char*不是字符串.它只是一个指向某个角色的指针,其惯例是可能有更多的角色要遵循,而在最后一个角色之后有一个角色'\0'.

C中的字符串文字(因此在C++中)就像"abc"是一个字符数组,编译器默默地添加一个'\0'.将数组分配给指针时,该数组会以静默方式将指针转换为第一个元素.结果是

at = "tw";
Run Code Online (Sandbox Code Playgroud)

意味着,指针at被赋予字符串文字中第一个字符的地址"tw".这样,它就会失去旧的价值.由于这是动态分配的字符数组的地址,因此您正在泄漏此数组.

当您稍后分配给at现在指向的数组中的字符时,您将为字符串文字中的某个字符分配新值.这是调用未定义的行为,程序挂起或立即崩溃可能是您执行此操作时可能发生的最佳情况.(在许多平台上,您正在写入只读内存.)

后来你传递atdelete[](而不是delete,因为你打电话new[],而不是new).在这样做时,您传递字符串文字的地址,而不是分配的字符数组.当然,这会弄乱堆管理器.(VC的运行时库在调试模式下捕获它.)

std::strcpy另一方面,将字符串中的字符串从一个数组复制到另一个数组.不会更改任何指针,只会复制内存块.之后指向目标数组的指针仍然指向目标数组,只有该数组中的数据已更改.

让我补充一点:作为C++的初学者,你应该使用std::string而不是C字符串.这为你做了所有肮脏的工作,并且具有理智的语义.


Bri*_*ndy 9

有三件事要理解:

1)char *at;只是一个指针变量.
指针变量只是意味着它保存了一个内存地址.

2)new char[3]返回堆上分配的内存的起始地址.

3)"hello"返回字符串文字的地址.

char *at = new char [3];
//at now contains the address of the memory allocated on the heap


at = "hello";
//at now contains the address of the static string. 
// (and by the way you just created a 3 byte memory leak)


delete[] at; 
//WOOPS!!!! you can't do that because you aren't deleting 
// the original 3 chars anymore which were allocated on the heap!
//Since at contains the string literal's memory address you're 
// trying to delete the string literal.
Run Code Online (Sandbox Code Playgroud)

关于修改只读内存的注意事项:

此外,您永远不应该修改字符串文字.也就是说,永远不应该这样做:

char *at = "hello";
at[2] = '\0'; 
Run Code Online (Sandbox Code Playgroud)

字符串文字的内存必须是只读的,如果更改它,结果将由C++语言定义.

因为你正在使用C++:

由于您使用的是C++,请考虑使用该std::string类型.

#include <string>

using namespace std;

int main(int argc, char **argv)
{
  string s = "hello";
  s += " world!";

  //s now contains "hello world!"

  s = "goodbye!";

  //Everything is still valid, and s contains "goodbye!"


  //No need to cleanup s. 

  return 0;
}
Run Code Online (Sandbox Code Playgroud)


ale*_*xkr 5

别忘了使用

delete []
Run Code Online (Sandbox Code Playgroud)

每当你用[]分配东西时.