std::字符串值或指针

std::string value or pointer?

本文关键字:指针 字符串 std      更新时间:2023-10-16

我从C++开始,在理解如何将std::string作为参数传递给函数方面遇到了一些困难。

void foo(std::string text)
{
    // ...
}
std::string data = "Hello World!";
foo(data);

在这种情况下,如果我没有错的话,字符串值会被传递给函数。因此,无论我对函数foo中的text变量做什么,都不会对data变量产生任何影响。

但是,对于某些函数(例如std::getline),我怎么可能以完全相同的方式传递字符串,而它们会更改其值呢?

std::string row;
std::getline(std::cin, row);
// now the value of row is changed

感谢

在C++中,您有几个选项:

  1. 传递值。函数原型是void foo(std::string text),您可以用foo(data);来调用它。您可以正确地观察到,在foodata中所做的任何修改都不会反映在调用者中。从概念上讲,会进行深度复制(如果这样做没有副作用,编译器可能会优化副本;但明智的做法是不要依赖它)。

  2. 通过引用传递。函数原型是void foo(std::string& text),您可以用foo(data);来调用它。在foodata中所做的任何修改都会反映在调用者中。

  3. 通过const参考。函数原型是void foo(const std::string& text),您称之为foo(data);。这是我最喜欢的:foo不允许修改data:这样的尝试会发出编译时错误。此外,不会获取字符串的深层副本。

  4. 传递指针。函数原型是void foo(std::string* text),您称之为foo(&data); foo可以修改字符串。

  5. 通过const指针。函数原型是void foo(const std::string* text),您称之为foo(&data);。与(3)中一样,foo无法修改传递的字符串。

由于1和2的调用语法相同,一些人不喜欢传递可以通过引用修改的内容,因为调用者不清楚参数是否可以更改。

通过引用传递:

void foo(std::string &text)
{
    // ...
}

您有几个选项可以在C++中传递变量

1) 按价值

void foo(std::string value) { /* ... */ }
// ... call
foo(data);

std::string的复制构造函数用于在foo中创建本地实例,修改保留在本地实例中。

2) 参考

void foo(std::string &value) { /* ... */ }
// ... call
foo(data);

参数变量被引用,因此foo中的value指向传递给函数的同一对象。更改反映在您的调用代码中。

3) 通过常量参考

void foo(const std::string &value) { /* ... */ }
// ... call
foo(data);

与(2)中一样,参数对象被引用,而不是创建新实例。但是,合同不会在foo中修改您的value。在内存和性能方面,这可能比复制整个字符串的(1)便宜。

4) 通过指针

void foo(std::string *value) { /* ... */ }
// ... call
foo(&data);

您将data的地址作为参数传递给foo。它类似于引用,只是依赖于指针逻辑。为了访问value中的字符串,您必须像在(*value)value->some_string_function() 中那样取消引用指针

5) 通过指向常量对象的指针

void foo(const std::string *value) { /* ... */ }
// ... call
foo(&data);

类似于(4),但是指针引用的对象是常量,就像引用情况(3)一样。请注意,指针本身不是常量,因此可以将其指向不同的对象。但是,指针是本地的(尽管指向的对象不是本地的),因此在foo内更改指针地址对data对象没有影响。

第二个参数是输出参数。std::getline(std::cin, row)