英文:
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
变量定义为类构造函数的参数并通过构造函数更新它是否是一种良好的做法。
例如:
假设test1
和test2
的其中一个定义在一个库类中,可以由不同的客户端实例化。
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<<"test1 "<<name_<<endl;
}
};
class test2{
public:
std::string name_;
test2 (std::string_view name): name_ {name} {};
void print() {
cout<<"test2 "<<name_<<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
- 底层数据的生命周期不同:
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.
-
Lifetime of the underlying data is different:
Test1 createTest1() { std::string tempName = "temporary"; 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.
-
std::string
will allocate data which is greater overhead over a version withstring_view
. -
You cannot modify
string_view
, its immutable (but it might change in c++23) -
Version with
std::string
requires more memory that the version withstd::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 ofstd::string
. -
The choice of
test1
vstest2
can greatly depend on how your application is structured, if you mostly passstring_view
-s then usetest1
, otherwise if you usestd::string
then usetest2
. -
std::string
supports more operations thanstd::string_view
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论