0

I have the following class:

class StringContainer {
  public:
    StringContainer(const std::string& s1, const std::string& s2) {  
      string_array_ = {s1, s2};
    }

  std::vector<std::string> string_array_;
};

and then I create an object from this struct like this:

StringContainer con(s1, s2);

where s1 and s2 are non const std::string variables defined locally. I noticed that the assignment of string_array_ from the initializer list does not call std::string's constructor at least once. (not for the temporary object in initializer list or for the object inserted to the vector). I have read that this may be possible for trivially constructable classes, but one of the requirements of trivially constructorbility is to have implicit default constructor/copy constructor. However std::string (std::basic_string) has both defined. What am I missing here? If I want to write a string class that would make use of this optimization, what should I do?

T.C.
  • 133,968
  • 17
  • 288
  • 421
user3612009
  • 655
  • 1
  • 6
  • 18
  • 3
    Which one of the many overloaded std::string constructors are you checking if it calls? – Klitos Kyriacou Dec 19 '15 at 15:02
  • 6
    I don't know how you know that the constructor for `std::string` is not called. I tell you that the constructor is called for each element in vector. The copy constructors are called in your example – bolov Dec 19 '15 at 15:03
  • I stepped through the debugger to the end and it never gets called. If I were to replace std::string with a user defined string, then I clearly see constructors getting called when the initializer list is constructed and when an item is added to the vector. – user3612009 Dec 19 '15 at 15:09
  • 2
    If you're building with optimization, isn't it possible that the calls are inlined so invisible to the debugger? You can try adding some "abort();" inside the string headers on your system temporarily to test it. – John Zwinck Dec 19 '15 at 15:15
  • Did you compile in debug mode? – Kerrek SB Dec 19 '15 at 15:23
  • It is common for debuggers to be set up to ignore method calls for classes in `std::` and silently step over them, under the assumption that most people don't want to debug the standard library. This makes the call to the constructor completely invisible in the debugger. Then too, the debugger may be unable to see inlined functions. There may be debugger control options somewhere you can set to change this; read up on your debugger's documentation. – Chris Dodd Dec 19 '15 at 16:52
  • Thanks for all comments, but my debugger steps through the std library (inside vector, etc) for sure. And I debugged a non optimized debug version and function inlining is also out of the question. – user3612009 Dec 19 '15 at 16:58

2 Answers2

1

I was convinced enough by my debugger that constructor is called however I decide to make little experiment to get proof if I could not use the debugger. You can try it by yourself too.

Create subclass of std::string, replace std::string in your code by string2, add some print outs and get the visual proof that the constructor was called:

class string2 : public string
{
public:
   string2(std::string s) : std::string(s)
   {
      std::cout << "string2 constructor" << std::endl;
   }
   string2(const string2& s) : std::string(s)
   {
      std::cout << "string2 copy constructor" << std::endl;
   }
};
StahlRat
  • 1,199
  • 13
  • 25
0

May it be because of COW?

See:

Quoting from the quote there:

*  This approach has the enormous advantage that a string object
*  requires only one allocation.  All the ugliness is confined
*  within a single %pair of inline functions, which each compile to
*  a single @a add instruction: _Rep::_M_data(), and
*  string::_M_rep(); and the allocation function which gets a
*  block of raw bytes and with room enough and constructs a _Rep
*  object at the front.

See also:

Community
  • 1
  • 1
mementum
  • 3,153
  • 13
  • 20