Should the std :: string element be a pointer?

And why / why?

Say I have a class that takes a string in a constructor and saves it. Should this class member be a pointer or just a value?

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

Or...

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

If I kept the primitive type, I would take a copy. If I were to store an object, I would use a pointer.

It seems to me that I want to copy this line, but I do not know when to solve it. Should I copy vectors? Kits? Cards? All JSON files ...?

EDIT:

It seems like I need to read the semantics of movement. But regardless, I would like to ask my question a little more specifically:

If I have a 10 megabyte file as a const string, I really don't want to copy it.

100 , 5 , . , .

(, ), , , class GenericTextHaver, text-have?

, const- const , , ?

+4
4

std::string ?

?

std::string, , ++ .

- . , , , ( , ), ... move-construction.

, , , . ? ? ? JSON...?

. " " ( , ) - .

-, , - . , , , . (, !)

, .

10- const, .

, . , std::move it.

100 , 5 , . , .

5 , . . , std::string , , . .

(, ) , , GenericTextHaver, text-have?

, . , , - . , , , -.

, const- const , , ?

. 2 , - , 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;
*/
}; 
+5

" ", , , std::string. - , , "":

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

    std::string s_;
};

, , .

+6

. std::string X, X . , - , std::unique_ptr<std::string> std::move:

class X {
public:
    std::unique_ptr<std::string> m_str;
    X(std::unique_ptr<std::string> str)
      : m_str(std::move(str)) { }
}

, , std:: unique_ptr . . , .

, , , std::shared_ptr<std::string> , .

0

, , , , , . -, , , X. , , X . -, X.s , ( ), X :

class X {
public:
  X(const string& val) {
    cout << "copied " << val << endl;
    s = new string(val);
  }

  X(string&& val) {
    cout << "moved " << val << endl;
    s = new string(std::move(val));
  }

  ~X() {
    delete s;
  }

private:
  const string *s;
};

int main() {
  string s = "hello world";
  X x1(s); // copy
  X x2("hello world"); // move

  return 0;
}

, , const *. (nullptr), , :

X(const string* val) : s(nullptr) {
    if(val != nullptr) 
      s = new string(*val);
}

These are the methods. When you design your class, the specifics of the problem at hand will determine whether you need to have a value or a pointer element.

0
source

Source: https://habr.com/ru/post/1620202/


All Articles