当前位置:  开发笔记 > 编程语言 > 正文

std :: string类成员应该是指针吗?

如何解决《std::string类成员应该是指针吗?》经验,为你挑选了2个好方法。

为什么/为什么不呢?

假设我有一个类,它在构造函数中包含一个字符串并存储它.这个类成员应该是一个指针,还是一个值?

class X {
    X(const std::string& s): s(s) {}
    const std::string s;
};

要么...

class X {
    X(const std::string* s): s(s) {}
    const std::string* s;
};

如果我存储原始类型,我会复制一份.如果我正在存储一个对象,我会使用一个指针.

我觉得我复制那个字符串,但我不知道何时决定.我应该复制载体吗?集?地图?整个JSON文件......?

编辑:

听起来我需要阅读移动语义.但无论如何,我想让我的问题更具体一些:

如果我有一个10兆字节的文件作为常量字符串,我真的不想复制它.

如果我正在新建100个对象,将5个字符的const字符串传递给每个构造函数,那么它们都不应该拥有所有权.可能只是拿一个字符串的副本.

所以(假设我并非完全错误)很明显该从课外做什么,但是当你在设计时,你class GenericTextHaver如何决定文本的方法呢?

如果你需要的是一个类,需要一个常量字符串在其构造,并让你获得一个常量字符串具有相同值吧,你怎么决定如何在内部表示呢?



1> Richard Hodg..:

std :: string类成员应该是指针吗?

没有

那么为何不?

因为std :: string与标准库中的每个其他对象一样,并且c ++中的所有其他编写良好的对象都被设计为被视为值.

它可能会也可能不会在内部使用指针 - 这不是您的关注点.所有你需要知道的是,它的编写精美,行为非常有效(实际上比你现在可能想象的更有效)当被视为一个值...特别是如果你使用移动构造.

我觉得我想复制那个字符串,但我不知道何时决定.我应该复制载体吗?集?地图?整个JSON文件......?

是.一个编写良好的类具有"值语义"(这意味着它被设计为被视为一个值) - 因此被复制和移动.

曾几何时,当我第一次编写代码时,指针通常是使计算机快速执行某些操作的最有效方法.现在,通过内存缓存,管道和预取,复制几乎总是更快.(对真的!)

在多处理器环境中,除了最极端的情况外,复制速度要快得多.

如果我有一个10兆字节的文件作为常量字符串,我真的不想复制它.

如果您需要它的副本,请复制它.如果你真的只想移动它,那么std::move它.

如果我正在新建100个对象,将5个字符的const字符串传递给每个构造函数,那么它们都不应该拥有所有权.可能只是拿一个字符串的副本.

一个5个字符的字符串复制起来很便宜,你甚至不应该考虑它.只需复制它.信不信由你,std::string完全知道大多数字符串很短,而且经常被复制.这里甚至不会参与任何内存分配.

所以(假设我并非完全错误)很明显该从课外做什么,但是当你设计类GenericTextHaver时,你如何决定文本的方法呢?

以最优雅的方式表达代码,简洁地传达您的意图.让编译器决定机器代码的外观 - 这是它的工作.成千上万的人已经花时间确保它比以往更好地完成这项工作.

如果您只需要一个在其构造函数中包含const字符串的类,并允许您从中获取具有相同值的const字符串,那么您如何决定如何在内部表示它?

几乎在所有情况下,都要存储副本.如果2个实例实际上需要共享相同的字符串,那么考虑别的东西,比如a std::shared_ptr.但在这种情况下,他们可能不仅需要共享一个字符串,所以'共享状态'应该封装在一些其他对象中(理想情况下是值语义!)

好的,别说了 - 告诉我课程应该怎么样

class X {
public:

    // either like this - take a copy and move into place
    X(std::string s) : s(std::move(s)) {}

   // or like this - which gives a *miniscule* performance improvement in a
   // few corner cases
/*
   X(const std::string& s) : s(s) {}  // from a const ref
   X(std::string&& s) : s(std::move(s)) {}  // from an r-value reference
*/

  // ok - you made _s const, so this whole class is now not assignable
  const std::string s;

  // another way is to have a private member and a const accessor
  // you will then be able to assign an X to another X if you wish

/*    
  const std::string& value() const {
    return s;
  }

private:
  std::string s;
*/
}; 



2> Kerrek SB..:

如果构造函数真正"接受一个字符串并存储它 ",那么你的类当然需要包含一个std::string数据成员.指针只会指向你实际上并不拥有的其他字符串,更不用说"存储"了:

struct X
{
    explicit X(std::string s) : s_(std::move(s)) {}

    std::string s_;
};

请注意,既然我们取得了字符串的所有权,我们也可以按值获取它,然后从构造函数参数中移除.

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有