C ++通过引用传递字符串vs传递char数组引用

时间:2018-03-22 18:01:48

标签: c++ arrays pointers stdstring

好的,所以我是C ++的新手,我只是想问为什么你不应该通过“&”引用传递char数组。签名,但你应该使用字符串,因为两个参数都是指针。我编写的示例代码:

void changeChar(char* buffer, int bSize) {
    strcpy_s(buffer, bSize, "test123");
}

void changeString(string* buffer) {
    *buffer = "test321";
}

char mychar[10] = "hello world";
string mystr;

changeChar(mychar, sizeof(mychar));
changeString(&mystr);

2 个答案:

答案 0 :(得分:1)

您需要知道,std::string不是内置类型。它是一个实现所有类型自定义行为的类,例如在对象复制时创建硬拷贝。

"some text" // this is a string literal, meaning the type is const char[num]

当您输入字符串文字时,它很可能位于名为“.rodata”的代码段内(只读数据)。你不能合法地修改这个字符的值。该文本还有一个“空终止符” - 结尾处的值为零的字符。它很有用,因为你需要知道文字何时结束。 num总是number of characters +1,因为空终结符。

当你这样写:

const char* text = "hello world!";
// note that this is illegal:
// char* text = "hello world!"; // literal is read-only.

你只是说:

  

text指向文字所在的内存。

复制文本实际上需要更多的工作。必须明确地完成:

char* notReadOnly = new char[30]; // you can allocate some more
// program will still interpret character of value 0 as the end, even if buffer is bigger
std::strcpy(notReadOnly, "hello world");
// use string literal as src in std::strcpy

注意,您也需要手动删除它:

delete[] notReadOnly;

std::string让它变得更容易。当你这样写时,它会自动复制文本:

std::string text = "some string literal";

std::string的复制构造函数也会制作缓冲区的硬拷贝。即使std::string类看起来像这样:

class string
{
    char *buffer;
    std::size_t numberOfCharacters;
};

每次复制时,都会执行buffer的硬拷贝,如下所示:

class string
{
    // rest
    string(const string &other)
    {
        numberOfCharacters = other.numberOfCharacters;
        buffer = new char[numberOfCharacters];
        // copy everything
        std::strncpy(buffer, other.buffer, numberOfCharacters);
    }
};

请注意,这只是一个简化的例子。

std::string a = "some text";
std::string b = a; // copy constructor is called. It uses method implemented above

const char* x = "some text2";
const char* y = x; // copy constructor is called. Only the address is copied, there is no hard copy of the actual buffer.

当您将变量作为参数传递给函数时,也会调用复制构造函数。在某些常见情况下,编译器可以对其进行优化。

答案 1 :(得分:1)

changeChar()char*指向位于内存中某处char指针(该函数假定char*实际指向{ {1}}指定大小的数组。)

固定长度数组衰减为指向其第一个元素的指针,仅由其名称引用。因此,当char[]指针占用operator&时,您无需(也不能)使用mychar[]changeChar()数组传递给char*函数。

如果您不想通过指针传递mychar,则必须通过引用传递它(否则,按值传递它将生成数组的副本,然后函数赢了&# 39; t能够修改原始数组)。在这种情况下,编译器可以为您推导出数组大小:

template<size_t size>
void changeChar(char (&buffer)[size]) {
    strcpy_s(buffer, size, "test123");
}

char mychar[] = "hello world";
changeChar(mychar);

changeString()string*指针指向内存中某处string对象。

您无法使用operator&(或std::addressof()当类重写operator&时)通过指针传递对象以获取对象的地址(除非已分配)使用new,在您的示例中并非如此)。

如果您不想通过指针传递string对象,则必须通过引用传递它(否则,按值传递对象将生成对象的副本,以及函数无法修改原始对象):

void changeString(string &buffer) {
    buffer = "test321";
}

string mystr;
changeString(mystr);