Need help in implementing move constructor for my string class.

Hi,

I am implementing my string class and stuck with an issue in defining move constructor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Str {
  private:
    char* c_str_;
  public:
    Str();
    Str(const char* str);
    Str(Str&& rval_str);
    ~Str();
};

Str::Str() : c_str_{nullptr} {} //default cnstructor

Str::Str(const char* str) {  // make string from const char*
  size_t size = strlen(str);
  c_str_ = new char[size + 1];
  strcpy(c_str_, str);
  c_str_[size] = '\0';
}

Str::Str(Str&& rval_str) {  //move constructor
  delete [] c_str_;
  c_str_ = rval_str.c_str_;
} 

Str::~Str() {        //destructor
  delete [] c_str_;
  c_str_ = nullptr;
}


int main() {
  Str s1{Str{"hello"}};  //[1]

/*
In the above line, a temporary (temp) object is created and the c_str_
of s1 will point to memory allocated to c_str_ of temp object.
Just after this line, the temp object will be deleted which will call
destructor for temp object that will call delete [] c_str_.

Wouldn't it invalidate the c_str_ of s1 also ?
*/

  return 0;
}


Thanks for the help

P.S. : Can anyone please help me with g++ compiler string implementation source file.
Last edited on
It seems almost ok. The idea is to move the string from rval_str to the local object.

1. You don't need to release a currently held string, because this is a new object, you don't have one.
2. Take ownership of the pointer, which you've done.
3. Remove the pointer from rval_str, which you haven't done.
The idea behind the move operation is that resources can be transferred rather than copied.
One wouldn't say delete when moving, but rather something like this:
1
2
3
4
5
6
7
8
9
10
11
// Take a shallow copy of rval_str.c_str_, and then set it to nullptr. 
// The referent of the argument is left with no string because this new
// string has stolen it 
Str::Str(Str&& rval_str) noexcept
  : c_str_{std::exchange(rval_str.c_str_, nullptr)}
{}

Str& Str::operator=(Str&& rval_str) noexcept
{
  c_str_ = std::exchange(rval_str.c_str_, nullptr);
}


Can anyone please help me with g++ compiler string implementation source file.
Does this mean you want someone to explain libstdc++'s implementation of std::string?

I feel like that would best be explained in person. In any event, it would be very challenging to explain completely to a beginner: decent implementations of std::string try very hard to be be as fast and as flexible as possible, and the resulting implementations are not friendly to beginners.

If you have specific questions, though...
Last edited on
Right, thanks. I've added the noexcept specifiers.
Last edited on
Also, it might be better to complete the assignment rather than leaving it posted in that illustrative form.
Thankyou everyone for your valuable inputs :).

Dear mbozzi

mbozzi wrote:
Does this mean you want someone to explain libstdc++'s implementation of std::string?

==> Actually I am looking for the source file of libstdc++'s implementation so that I could see the difference in basic code structure in my code and the library implementation and learn about the things which I have missed in my string class implementation. Eg. "marking the move user-defined move operations as noexcept".

Kindly let me know if there is a way to get library implementation of string.

Thanks
Last edited on
Kindly let me know if there is a way to get library implementation of string.

It should just be a header file, in which case it will already be installed as part of your development environment. If you don't know where it's been installed to, use whatever "find file" utilities your OS has to find it.

However, be advised: mbozzi is right. It will almost certainly be challenging to understand.
Last edited on
> Actually I am looking for the source file of libstdc++'s implementation so that I could see the difference
> in basic code structure in my code and the library implementation and learn about the things which I have missed
> in my string class implementation.

The standard library implementation of string is significantly different from your implementation.
1
2
3
4
5
template< 
    class CharT, 
    class Traits = std::char_traits<CharT>, 
    class Allocator = std::allocator<CharT>
> class basic_string;

https://en.cppreference.com/w/cpp/string/basic_string

It is implemented as an abstraction that is independent of the specific character type (and the properties of the character type) that is used.
Character types and traits: http://www.angelikalanger.com/Articles/C++Report/CharacterTraits/CharacterTraits.html

It is also independent of specific memory management and allocation strategies.
Allocators (C+++98): http://www.angelikalanger.com/Articles/C++Report/Allocators/Allocators.html

The libc++ implementation of std::basic_string:
https://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?revision=349178&view=markup

Note that like most implementations, it too has small string optimisation:
See 'Small Object Optimization': https://shaharmike.com/cpp/std-string/
Thanks @JLBorges for the library implementation link.

Thanks @MikeyBoy for your inputs.
Topic archived. No new replies allowed.