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

2skhul33  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(177)

好的,我是C++的新手,我只是想问为什么你不应该通过引用传递字符数组,而应该传递字符串,因为两个参数都是指针。我写的示例代码:

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);
jrcvhitl

jrcvhitl1#

changeChar()使用一个char*指针指向位于内存中 * 某处 * 的char(函数假设char*实际上指向指定大小的char[]数组的第一个char)。
任何固定长度的数组衰减成为一个指针,指向它的第一个元素,当它只引用它的名字。因此,当char*函数接受char*指针时,没有必要(也不能)使用operator&mychar[]数组传递给changeChar()函数。
如果不想通过指针传递mychar,则必须通过引用传递(否则,通过值传递将复制数组,然后函数将无法修改原始数组)。在这种情况下,必须将数组的大小作为引用所使用的数据类型的一部分,例如:

void changeChar(char (&buffer)[12]) {
    strcpy_s(buffer, 12, "test123");
}

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

但是,只有当传递给函数的所有数组大小相同时,这才起作用。如果你需要传递不同大小的数组,请将函数改为模板,这样编译器就可以推断传入的数组的大小,例如:

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

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

changeString()接受一个string*指针,指向位于内存中某个地方的string对象。
如果不使用operator&(或者当类重写operator&时使用std::addressof())来获取对象的地址,就不能通过指针传递对象(除非它被分配了new,而在您的示例中不是这种情况)。
如果你不想通过指针传递string对象,你必须通过引用传递它(否则,通过值传递对象将复制对象,函数将无法修改原始对象):

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

string mystr;
changeString(mystr);
bnl4lu3b

bnl4lu3b2#

您需要知道,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.

当你把变量作为参数传递给一个函数时,也会调用复制构造函数。编译器可以在一些常见的情况下优化它。

相关问题