是在构造函数中分配一个std::string_view类型一个好主意吗?

huangapple go评论79阅读模式
英文:

Is it a good idea to assign a std::string_view type in constructor?

问题

我明白使用std::string_view比使用std::string更好,因为它允许传递const char*std::string值,而不需要创建std::string对象。此外,我理解它提供了只读访问。

但是,我想知道是否将一个公共的std:string_view变量定义为类构造函数的参数并通过构造函数更新它是否是一种良好的做法。

例如:
假设test1test2的其中一个定义在一个库类中,可以由不同的客户端实例化。

class test1{
public:
 std::string_view name_;
 
 test1(std::string_view name): name_ {name} {};
 void print() {
     cout << "test1 " << name_ << endl;
 }
};

class test2{
public:
 std::string name_;
 
 test2(std::string_view name): name_ {name} {};
 void print() {
     cout << "test2 " << name_ << endl;
 }

};
英文:

I understand that using std::string_view is better than std::string because it allows const char* and std::string values to be passed without needing a std::string object to be created.
Also i understand the it provides a ReadOnly access

However, i was wondering if it is a good practice to define a public std:string_view variable and update it through the class constructor.

i.e:
What is the difference between test1 and test2, assuming test1 or test2 is defined in a library class which can be instantiated by different clients.

class test1{
public:
 std::string_view name_;
 
 test1 (std::string_view name): name_ {name} {};
 void print() {
     cout&lt;&lt;&quot;test1 &quot;&lt;&lt;name_&lt;&lt;endl;
 }
};

class test2{
public:
 std::string name_;
 
 test2 (std::string_view name): name_ {name} {};
 void print() {
     cout&lt;&lt;&quot;test2 &quot;&lt;&lt;name_&lt;&lt;endl;
 }

};

答案1

得分: 3

虽然这不是完全错误的,但它有潜在的不安全性。用户使用该类时非常重要的一点是要理解成员变量仅在指向的字符串的生命周期内有效,这个生命周期可能比对象的生命周期更短。这应该清晰地记录下来,并且类的名称应该反映其引用性质。一些示例包括后缀如 _view_ref

在必须要求生命周期比指向的字符串长的情况下,test1 类将不会有用。这与使用类型为 const char* 的成员变量时的考虑相同。

英文:

While it's not wrong as such, it's potentially unsafe. It's extremely important for the user of the class to understand that the member will remain valid only as long as the pointed string's lifetime, which may be shorter than that of the object. It should be both documented clearly, and the name of the class should reflect its referential nature. Some examples are suffixes such as _view or _ref.

The class test1 won't be useful in such cases where the lifetime must be longer than that of the pointed string. This consideration is same as when using a member of type const char*.

答案2

得分: 2

  1. 底层数据的生命周期不同:
Test1 createTest1() {
   std::string tempName = "temporary";
   return Test1(tempName);
}
// 这里 name_ 将成为悬空引用,这是未定义行为
test1 a = createTest1();

 test2 的情况下不会发生这种问题。

2. `std::string` 将分配更多的数据,这对于带有 `string_view` 版本来说是更大的开销。
3. 无法修改 `string_view`,它是不可变的(但在 C++23 中可能会改变)。
4. 带有 `std::string` 的版本需要更多的内存,即使在 SSO 模式下,也需要一些字节数组来存储小字符串,而这个数组通常是 `std::string` 的最小大小。
5. 选择 `test1`  `test2` 可能会在你的应用程序结构如何组织上有很大影响,如果你主要传递 `string_view`,则使用 `test1`,否则如果你使用 `std::string`,则使用 `test2`。
6. `std::string` 支持比 `std::string_view` 更多的操作。
英文:

There are important differences.

  1. Lifetime of the underlying data is different:

     Test1 createTest1() {
        std::string tempName = &quot;temporary&quot;;
        return Test1(tempName);
     }
     // here name_ will become a dangling reference, this is UB
     test1 a = createTest1();
    

    No such problem will happen in case of test2.

  2. std::string will allocate data which is greater overhead over a version with string_view.

  3. You cannot modify string_view, its immutable (but it might change in c++23)

  4. Version with std::string requires more memory that the version with std::string_view. std::string even when in SSO mode requires, some array of bytes to store small strings, and this array is usually a minimal size of std::string.

  5. The choice of test1 vs test2 can greatly depend on how your application is structured, if you mostly pass string_view-s then use test1, otherwise if you use std::string then use test2.

  6. std::string supports more operations than std::string_view.

huangapple
  • 本文由 发表于 2023年7月7日 04:29:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76632346.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定