将 char 数组传递给需要 const std::string 引用的函数
Passing a char array to a function that expects a const std::string reference
我在不久前写的套接字接口中犯了一个错误,我只是在查看代码以查找其他问题时才注意到这个问题。 socket接收到一串字符,传递给jsoncpp完成json解析。我可以几乎 理解这里发生的事情,但我无法理解它。我想了解引擎盖下实际发生的事情。这是最小的例子:
#include <iostream>
#include <cstring>
void doSomethingWithAString(const std::string &val) {
std::cout << val.size() << std::endl;
std::cout << val << std::endl;
}
int main()
{
char responseBufferForSocket[10000];
memset(responseBufferForSocket, 0, 10000);
//Lets simulate a response from a socket connection
responseBufferForSocket[0] = 'H';
responseBufferForSocket[1] = 'i';
responseBufferForSocket[2] = '?';
// Now lets pass a .... the address of the first char in the array...
// wait a minute..that's not a const std::string& ... but hey, it's ok it *works*!
doSomethingWithAString(responseBufferForSocket);
return 0;
}
上面的代码没有引起任何明显的问题,但如果有问题我想更正它。显然字符数组正在转换为字符串,但通过什么机制呢?我想我有四个问题:
- 此字符串是在堆栈上转换并通过引用传递还是通过值传递?
- 是否使用 operator= 重载?一个“来自 c 字符串”的构造函数?其他一些机制?
- 基于 2,这是否比使用构造函数显式转换为字符串效率低?
- 这危险吗。 :)
用 g++ 编译 (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
std::string
有一个 非显式 构造函数(即未标记 explicit
关键字),它采用 const char*
参数并复制字符直到第一个 '[=13=]'
(如果字符串中不存在这样的字符,则行为未定义)。换句话说,它执行源数据的副本。 It's overload #5 on this page.
const char[]
隐式衰减为 const char*
,您可以将临时值传递给采用 const
引用参数的函数。顺便说一下,这仅在引用为 const
时有效;如果你不能使用const
,按值传递它。
因此,当您将 const char[]
传递给该函数时,将使用该构造函数构造一个 std::string
类型的临时对象,并绑定到参数。临时文件将在函数调用期间保持活动状态,并在 returns.
时被销毁
考虑到所有这些,让我们来解决您的问题:
- 它是通过引用传递的,但引用是对临时对象的引用。
- 一个构造函数,因为我们正在构造一个对象。
std::string
也有一个 operator=
接受一个 const char*
参数,但它从未用于隐式转换:你需要显式分配一些东西。
- 由于运行相同的代码,性能是相同的,但是您确实会产生一些开销,因为数据是复制的而不是引用的。如果这是一个问题,请改用
std::string_view
。
- 只要您不尝试保留对参数的引用或指针的时间超过函数调用,这是安全的,因为该对象之后可能不存在(但是您应该始终牢记这一点参考参数)。您还需要确保您传递的 C 字符串正确地以 null 结尾。
- Is this string converted on the stack
该语言没有指定临时对象的存储方式,但在这种情况下它可能存储在堆栈中,是的。
or is it passed by value?
参数为参考。因此,您是“通过引用传递”。
- Is it using the operator= overload?
没有。您没有在此处使用 operator=,那为什么要使用它?
A "from c-string" constructor?
是的。
- Based on 2 is this less efficient in than converting to a string explicitly using a constructor?
没有。对象是隐式创建还是显式创建与效率无关。
然而,创建 std::string
可能比不创建它效率低,您可以通过不接受对字符串的引用作为参数来实现。您可以改用字符串视图。
- Is this dangerous.
不特别。在某些情况下,当程序员没有注意到隐式转换时,隐式转换可能会导致一些问题,但通常它们会通过减少冗长来简化语言。
我在不久前写的套接字接口中犯了一个错误,我只是在查看代码以查找其他问题时才注意到这个问题。 socket接收到一串字符,传递给jsoncpp完成json解析。我可以几乎 理解这里发生的事情,但我无法理解它。我想了解引擎盖下实际发生的事情。这是最小的例子:
#include <iostream>
#include <cstring>
void doSomethingWithAString(const std::string &val) {
std::cout << val.size() << std::endl;
std::cout << val << std::endl;
}
int main()
{
char responseBufferForSocket[10000];
memset(responseBufferForSocket, 0, 10000);
//Lets simulate a response from a socket connection
responseBufferForSocket[0] = 'H';
responseBufferForSocket[1] = 'i';
responseBufferForSocket[2] = '?';
// Now lets pass a .... the address of the first char in the array...
// wait a minute..that's not a const std::string& ... but hey, it's ok it *works*!
doSomethingWithAString(responseBufferForSocket);
return 0;
}
上面的代码没有引起任何明显的问题,但如果有问题我想更正它。显然字符数组正在转换为字符串,但通过什么机制呢?我想我有四个问题:
- 此字符串是在堆栈上转换并通过引用传递还是通过值传递?
- 是否使用 operator= 重载?一个“来自 c 字符串”的构造函数?其他一些机制?
- 基于 2,这是否比使用构造函数显式转换为字符串效率低?
- 这危险吗。 :)
用 g++ 编译 (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
std::string
有一个 非显式 构造函数(即未标记 explicit
关键字),它采用 const char*
参数并复制字符直到第一个 '[=13=]'
(如果字符串中不存在这样的字符,则行为未定义)。换句话说,它执行源数据的副本。 It's overload #5 on this page.
const char[]
隐式衰减为 const char*
,您可以将临时值传递给采用 const
引用参数的函数。顺便说一下,这仅在引用为 const
时有效;如果你不能使用const
,按值传递它。
因此,当您将 const char[]
传递给该函数时,将使用该构造函数构造一个 std::string
类型的临时对象,并绑定到参数。临时文件将在函数调用期间保持活动状态,并在 returns.
考虑到所有这些,让我们来解决您的问题:
- 它是通过引用传递的,但引用是对临时对象的引用。
- 一个构造函数,因为我们正在构造一个对象。
std::string
也有一个operator=
接受一个const char*
参数,但它从未用于隐式转换:你需要显式分配一些东西。 - 由于运行相同的代码,性能是相同的,但是您确实会产生一些开销,因为数据是复制的而不是引用的。如果这是一个问题,请改用
std::string_view
。 - 只要您不尝试保留对参数的引用或指针的时间超过函数调用,这是安全的,因为该对象之后可能不存在(但是您应该始终牢记这一点参考参数)。您还需要确保您传递的 C 字符串正确地以 null 结尾。
- Is this string converted on the stack
该语言没有指定临时对象的存储方式,但在这种情况下它可能存储在堆栈中,是的。
or is it passed by value?
参数为参考。因此,您是“通过引用传递”。
- Is it using the operator= overload?
没有。您没有在此处使用 operator=,那为什么要使用它?
A "from c-string" constructor?
是的。
- Based on 2 is this less efficient in than converting to a string explicitly using a constructor?
没有。对象是隐式创建还是显式创建与效率无关。
然而,创建 std::string
可能比不创建它效率低,您可以通过不接受对字符串的引用作为参数来实现。您可以改用字符串视图。
- Is this dangerous.
不特别。在某些情况下,当程序员没有注意到隐式转换时,隐式转换可能会导致一些问题,但通常它们会通过减少冗长来简化语言。