我应该使用 unique_ptr 作为字符串吗?
Should I use unique_ptr for a string?
我是 C++ 新手。我听说使用 unique_ptr
/ shared_ptr
是引用堆上分配的数据的“方法”。因此,使用 unique_ptr
s 而不是 std::string
s 有意义吗?
不需要使用 std::unique_ptr
or std::shared_ptr
for a std::string
。
您不必为简单的 std::string
.
分配内存
std::string str = "abc";
就这么简单。不需要内存分配,因为 std::string
自己管理 'real' 字符串。
有些情况可能会导致使用指针,尽管它很可能是 class/struct 实例。
例如考虑使用
std::unique_ptr<MyClass> p;
而不是
MyClass *p;
如果可能的话。
您通常不需要指向字符串的指针,就像您通常不需要指向整数的指针一样。您可以只存储字符串值,也可以传递字符串值等。
但是如果您处于需要指向字符串的指针的特殊情况,那么是的,std::unique_ptr<std::string>
或 std::shared_ptr<std::string>
比 std::string*
更好。
你为什么要这样做?
std::string 对象自行管理 "contained" 字符串(内存字节)的生命周期。
由于您是 C++ 新手。在你的 function / class 方法中,我会建议你在堆栈上创建你的对象:
像这样:
std::string s;
相对于使用堆:
std::string* s = new std::string();
当您的对象超出范围时,在堆栈上创建的对象将被销毁。所以不需要智能指针。
你可以关注这个link了解更多:http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
std::unique_ptr
确保指向的对象不会被意外复制并正确删除。
由于您应该尽可能避免动态分配,因此您可以简单地将 std::string
作为 class 的成员。如果它是一个返回值,正如已经指出的那样,字符串 class 足够聪明,可以安全地正确移动资源。
你不需要保证一个字符串是唯一的,我的意思是,不存在副本,所以唯一的 ptr 只是一个太强的约束。
KIS 规则:保持简单。
通常,默认情况下,答案是否定的,正如其他人所建议的那样。然而 - 有时,答案可能自相矛盾地是“可能是”!怎么会?
- 使用
std::string
,您无法控制缓冲区的分配方式、时间和分配者。虽然如果您使用不同的分配器 (std::basic_string<char, MyAllocatorType>
),这会有所缓解 - 结果 class 是 not std::string
;并且通常不会被采用 std::string
的函数所接受。仅仅为了这个目的而进入分配器可能没有意义。
- 更具体地说,您可以允许将 unique-pointer-based 字符串 class 创建为现有缓冲区的拥有包装器。
- 现在我们可以使用
string_view
- 它们甚至在 C++20 的标准中 (std::string_view
) - 你不必重写整个字符串 class 用于 unique-pointer-based 字符串;您所需要的只是在其上创建一个字符串视图,使用原始指针和以字节为单位的大小(如果您想要更好的 null-termination 安全性,则大小为 1。)如果您确实想要 std::string 方法尽管如此,它们还是 one-liners,例如
std::string_view view() const {
return std::string_view{uptr_.get(), size_};
}
substr(size_type pos = 0, size_type count = npos) const {
return view().substr(pos, count);
}
- 如果您想更新字符串 in-place,同时保持其大小 -
std::string
将不适合您:要么它完全不变,要么大小和内容都可变。
我是 C++ 新手。我听说使用 unique_ptr
/ shared_ptr
是引用堆上分配的数据的“方法”。因此,使用 unique_ptr
s 而不是 std::string
s 有意义吗?
不需要使用 std::unique_ptr
or std::shared_ptr
for a std::string
。
您不必为简单的 std::string
.
std::string str = "abc";
就这么简单。不需要内存分配,因为 std::string
自己管理 'real' 字符串。
有些情况可能会导致使用指针,尽管它很可能是 class/struct 实例。
例如考虑使用
std::unique_ptr<MyClass> p;
而不是
MyClass *p;
如果可能的话。
您通常不需要指向字符串的指针,就像您通常不需要指向整数的指针一样。您可以只存储字符串值,也可以传递字符串值等。
但是如果您处于需要指向字符串的指针的特殊情况,那么是的,std::unique_ptr<std::string>
或 std::shared_ptr<std::string>
比 std::string*
更好。
你为什么要这样做?
std::string 对象自行管理 "contained" 字符串(内存字节)的生命周期。
由于您是 C++ 新手。在你的 function / class 方法中,我会建议你在堆栈上创建你的对象: 像这样:
std::string s;
相对于使用堆:
std::string* s = new std::string();
当您的对象超出范围时,在堆栈上创建的对象将被销毁。所以不需要智能指针。
你可以关注这个link了解更多:http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/
std::unique_ptr
确保指向的对象不会被意外复制并正确删除。
由于您应该尽可能避免动态分配,因此您可以简单地将 std::string
作为 class 的成员。如果它是一个返回值,正如已经指出的那样,字符串 class 足够聪明,可以安全地正确移动资源。
你不需要保证一个字符串是唯一的,我的意思是,不存在副本,所以唯一的 ptr 只是一个太强的约束。
KIS 规则:保持简单。
通常,默认情况下,答案是否定的,正如其他人所建议的那样。然而 - 有时,答案可能自相矛盾地是“可能是”!怎么会?
- 使用
std::string
,您无法控制缓冲区的分配方式、时间和分配者。虽然如果您使用不同的分配器 (std::basic_string<char, MyAllocatorType>
),这会有所缓解 - 结果 class 是 notstd::string
;并且通常不会被采用std::string
的函数所接受。仅仅为了这个目的而进入分配器可能没有意义。 - 更具体地说,您可以允许将 unique-pointer-based 字符串 class 创建为现有缓冲区的拥有包装器。
- 现在我们可以使用
string_view
- 它们甚至在 C++20 的标准中 (std::string_view
) - 你不必重写整个字符串 class 用于 unique-pointer-based 字符串;您所需要的只是在其上创建一个字符串视图,使用原始指针和以字节为单位的大小(如果您想要更好的 null-termination 安全性,则大小为 1。)如果您确实想要 std::string 方法尽管如此,它们还是 one-liners,例如std::string_view view() const { return std::string_view{uptr_.get(), size_}; } substr(size_type pos = 0, size_type count = npos) const { return view().substr(pos, count); }
- 如果您想更新字符串 in-place,同时保持其大小 -
std::string
将不适合您:要么它完全不变,要么大小和内容都可变。