简体   繁体   English

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

[英]C++ pass string by reference vs pass char array by reference

Okay so I'm new to C++ and I just wanted to ask why you shouldn't pass the char array by reference with the "&" sign but you should with strings since both arguments are pointers. 好的,所以我是C ++的新手,我只是想问一个问题,为什么您不应该通过引用带有“&”符号的char数组来传递,而应该使用字符串,因为这两个参数都是指针。 Example code I have written: 我编写的示例代码:

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

You need to know, that std::string is not a built-in type. 您需要知道, std::string不是内置类型。 It is a class, that implements all kind of custom behaviour, such as creating hard copy on object copying. 这是一个类,可实现各种自定义行为,例如在对象复制上创建硬拷贝。

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

When you enter a string literal, it is located most likely inside section of the code named ".rodata" (read only data). 当您输入字符串文字时,它很可能位于名为“ .rodata”的代码的内部(只读数据)。 You cannot legaly modify value of this characters. 您不能合法地修改此字符的值。 The text has also a "null terminator" - character of value of zero at the end. 文本中还有一个“空终止符”-末尾的值为零的字符。 It is useful, because you need to know when the literal ends. 这很有用,因为您需要知道文字何时结束。 num is always number of characters +1 , because of the null terminator. 由于空终止符, num始终number of characters +1

When you write this: 当您编写此代码时:

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

You just say: 你只是说:

let text point to the memory, where the literal is located. text指向文字所在的内存。

Copying text actually requires from as more work. 实际上,复制文本需要进行更多工作。 It must be done explicitly: 必须明确完成:

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

Note, that you need to manually delete it too: 请注意,您也需要手动将其删除:

delete[] notReadOnly;

std::string makes it a lot easier. std::string使它变得更加容易。 It automatically copies the text, when you write sth like this: 当您这样写时,它会自动复制文本:

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

std::string 's copy constructor also makes hard copy of the buffer. std::string的副本构造函数还会对缓冲区进行硬拷贝。 Even if std::string class looked like this: 即使std::string类看起来像这样:

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

Every time its copied, it performs hard copy of the buffer , which can look like this: 每次复制时,它都会执行buffer硬拷贝,如下所示:

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

Note, that this is just a simplified example. 注意,这只是一个简化的示例。

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.

Copy constructors are also called, when you pass variable to a function as parameter. 当您将变量作为参数传递给函数时,也会调用复制构造函数。 Compilers can optimize it however in some common cases. 但是,在某些常见情况下,编译器可以对其进行优化。

changeChar() takes a char* pointer to a char located somewhere in memory (the function assumes the char* is actually pointing to a char[] array of the specified size). changeChar()使用char*指针指向位于内存中某处char (该函数假定char*实际上指向指定大小的char[]数组)。

A fixed-length array decays into a pointer to its 1st element when referred to by just its name. 当仅由其名称引用时,定长数组会衰减为指向其第一个元素的指针。 So there is no need to (nor can you) use operator& to pass your mychar[] array to your changeChar() function when it takes a char* pointer. 因此,当它使用char*指针时,不需要(也不能)使用operator&mychar[]数组传递给changeChar()函数。

If you don't want to pass mychar by pointer, you have to pass it by reference instead (otherwise, passing it by value will make a copy of the array, and then the function won't be able to modify the original array). 如果你不希望传递mychar的指针,你必须按引用传递它,而不是(否则,按值传递就会使数组的副本,然后该函数将不能修改原始数组) 。 In which case, the compiler can deduce the array size for you: 在这种情况下,编译器可以为您推断出数组大小:

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

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

changeString() takes a string* pointer to a string object located somewhere in memory. changeString()使用string*指针指向位于内存中某处string对象。

You can't pass an object by pointer without using operator& (or std::addressof() when a class overrides operator& ) to get the address of the object (unless it was allocated with new , which is not the case in your example). 如果没有使用operator& (或当类重写operator&时使用std::addressof() )来获取对象的地址,则不能通过指针传递对象(除非它被分配了new ,在本例中不是这种情况) 。

If you don't want to pass the string object by pointer, you have to pass it by reference instead (otherwise, passing the object by value will make a copy of the object, and the function won't be able to modify the original object): 如果你不希望传递的string通过指针对象,你必须按引用传递它,而不是(否则,按值传递的对象将使得对象的副本,并且功能将不能修改原来的宾语):

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

string mystr;
changeString(mystr);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM