从 char* 移动 std::string 的构造函数
Move constructor for std::string from char*
我有一个函数 f
返回 char*
。函数文档说:
The user must delete returned string
我想从中构建一个 std::string
。琐碎的事情是:
char* cstring = f();
std::string s(cstring);
delete cstring;
是否可以使用 C++ 功能做得更好?我想写点像
std::string(cstring)
避免泄漏。
std::string
没有标准方法来获取您传递的缓冲区的所有权。
也不负责清理此类缓冲区。
理论上,了解所有内部细节的实现,可以添加一种方法让 std::string
接管使用其分配器分配的缓冲区,但我不'知道有任何实现。
也不能保证这样做实际上是有利的,具体取决于实施细节。
std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
std::string s = buff?buff.get():""; // handle null pointers
return s;
}
std::string steal_char_buffer( const char* str ) {
std::unique_ptr<char[]> buff(str); // manage lifetime
return steal_char_buffer(std::move(buff));
}
现在您可以输入
std::string s = steal_char_buffer(f());
你从 f()
中得到 std::string
。
您可能想要使 steal_char_buffer
的参数成为 const char*&&
。这大部分是没有意义的,但它可能会导致一些有用的错误。
如果你能改变f
的界面,直接return变成std::string
或者std::unique_ptr<char[]>
.
另一个好主意是将 f
包装在另一个 return 是 std::unique_ptr<char[]>
或 std::string
:
的函数中
std::unique_ptr<char[]> good_f() {
return std::unique_ptr<char[]>(f());
}
and/or
std::string good_f2() {
auto s = good_f();
return steal_char_buffer( std::move(s) );
}
std::string
将制作一个空终止字符串参数的副本并管理该副本。没有办法让它拥有您传递给它的字符串的所有权。所以你所做的是正确的,我建议的唯一改进是检查 nullptr
,假设这是 f()
的有效 return 值。这是必要的,因为采用 char const *
的 std::string
构造函数要求参数指向有效数组,而不是 nullptr
.
char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring; // You most likely want delete[] and not delete
现在,如果您不需要 std::string
的所有界面,或者如果避免复制很重要,那么您可以使用 unique_ptr
来管理字符串。
std::unique_ptr<char[]> s{f()}; // will call delete[] automatically
您可以通过 s.get()
访问托管的 char *
,当 s
超出范围时,字符串将为 delete
d。
即使您选择第一个选项,我也建议在将 f()
的 return 值传递给 std::string
构造函数之前将其存储在 unique_ptr
中.这样,如果构造失败,returned 字符串仍将被删除。
此代码永远不会正确:
std::string s(cstring);
delete cstring;
采用字符指针的 std::string
构造函数需要一个以 NUL 结尾的字符串。所以它是多个个字符。
delete cstring
是标量删除。
您是否正在尝试从字符标量创建字符串(在这种情况下,为什么要间接访问?)
std::string s(cstring[0]);
delete cstring;
或者你有多个字符,应该相应删除
std::string s(cstring);
delete [] cstring;
检查推荐方法的其他答案以确保使用 delete[]
,例如
std::string(std::unique_ptr<char[]>(f()).get())
我有一个函数 f
返回 char*
。函数文档说:
The user must delete returned string
我想从中构建一个 std::string
。琐碎的事情是:
char* cstring = f();
std::string s(cstring);
delete cstring;
是否可以使用 C++ 功能做得更好?我想写点像
std::string(cstring)
避免泄漏。
std::string
没有标准方法来获取您传递的缓冲区的所有权。
也不负责清理此类缓冲区。
理论上,了解所有内部细节的实现,可以添加一种方法让 std::string
接管使用其分配器分配的缓冲区,但我不'知道有任何实现。
也不能保证这样做实际上是有利的,具体取决于实施细节。
std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
std::string s = buff?buff.get():""; // handle null pointers
return s;
}
std::string steal_char_buffer( const char* str ) {
std::unique_ptr<char[]> buff(str); // manage lifetime
return steal_char_buffer(std::move(buff));
}
现在您可以输入
std::string s = steal_char_buffer(f());
你从 f()
中得到 std::string
。
您可能想要使 steal_char_buffer
的参数成为 const char*&&
。这大部分是没有意义的,但它可能会导致一些有用的错误。
如果你能改变f
的界面,直接return变成std::string
或者std::unique_ptr<char[]>
.
另一个好主意是将 f
包装在另一个 return 是 std::unique_ptr<char[]>
或 std::string
:
std::unique_ptr<char[]> good_f() {
return std::unique_ptr<char[]>(f());
}
and/or
std::string good_f2() {
auto s = good_f();
return steal_char_buffer( std::move(s) );
}
std::string
将制作一个空终止字符串参数的副本并管理该副本。没有办法让它拥有您传递给它的字符串的所有权。所以你所做的是正确的,我建议的唯一改进是检查 nullptr
,假设这是 f()
的有效 return 值。这是必要的,因为采用 char const *
的 std::string
构造函数要求参数指向有效数组,而不是 nullptr
.
char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring; // You most likely want delete[] and not delete
现在,如果您不需要 std::string
的所有界面,或者如果避免复制很重要,那么您可以使用 unique_ptr
来管理字符串。
std::unique_ptr<char[]> s{f()}; // will call delete[] automatically
您可以通过 s.get()
访问托管的 char *
,当 s
超出范围时,字符串将为 delete
d。
即使您选择第一个选项,我也建议在将 f()
的 return 值传递给 std::string
构造函数之前将其存储在 unique_ptr
中.这样,如果构造失败,returned 字符串仍将被删除。
此代码永远不会正确:
std::string s(cstring);
delete cstring;
采用字符指针的 std::string
构造函数需要一个以 NUL 结尾的字符串。所以它是多个个字符。
delete cstring
是标量删除。
您是否正在尝试从字符标量创建字符串(在这种情况下,为什么要间接访问?)
std::string s(cstring[0]);
delete cstring;
或者你有多个字符,应该相应删除
std::string s(cstring);
delete [] cstring;
检查推荐方法的其他答案以确保使用 delete[]
,例如
std::string(std::unique_ptr<char[]>(f()).get())