Zebrafish
Zebrafish

Reputation: 13876

C++ const string literals and custom string class

In C++ string literals "Hello" are const and are immutable. I wanted to make a custom string class whose strings are not const chars, so they can be changeable

Here is a snippet of code that might illustrate what I'm trying to do:

#include <iostream>

class String {
  public: 
    char * p_start;

    String(char * strSourc) // Constructor
      {
        p_start = strSourc;
      }
};

int main() 
{
  String myString("Hello");  
// Create object myString, send "Hello" string literal as argument

  std::cout << myString.p_start << std::endl; 
// Prints "Hello"

  *myString.p_start = 'Y'; 
// Attempt to change value at first byte of myString.p_start

  std::cout << myString.p_start << std::endl; 
// Prints "Hello" (no change)

  myString.p_start = "Yellow"; 
// Assigning a string literal to p_start pointer 

  std::cout << myString.p_start << std::endl; 
// Prints Yellow, change works.  I thought myString "Hello" was const chars, immutable

  return 0;
}

So, I'm confused. I've looked everywhere and it says that string literals, like "Hello", are immutable, each of their char bytes are unchangeable. Though I managed to assign Yellow to the p_start pointer, changing the first letter. Though changing the single letter H to a Y through dereferencing the H pointer didn't do anything.

Any insights would help me, thanks.

Upvotes: 0

Views: 841

Answers (2)

MP3D
MP3D

Reputation: 41

not sure if anyone finds this helpful after so long but since I am learning myself I took your above code and made it work by copying. It now has a member variable for size and cleans up using delete when you assign a new string literal to it (const char*).

#include <iostream>

class String {
public: 
char * p_start;
int m_size;

String(const char * strSourc) // Constructor
  {
    //The following will get the size of the parameter.
     int SizeParameter=0;
     while (*(strSourc+SizeParameter) != '\0')
     {
         SizeParameter++;
     }
     // size of string saved.
     m_size = SizeParameter; 
     // allocate enough memory so we can copy strSourc
     p_start = new char[SizeParameter+1];
     //copy the contents strSourc
    for(int i=0; i<SizeParameter+1; i++)
    {
    *(p_start+i) = *(strSourc+i);
    }
  }
  //Handle change of string value.
  char* AssignNewString (const char* newtext)
  {
      //clean
      delete p_start; 
      
      int SizeParameter=0;
     while (*(newtext+SizeParameter) != '\0')
     {
         SizeParameter++;
     }
     // size of string saved.
     m_size = SizeParameter; 
     // allocate enough memory so we can copy strSourc
     p_start = new char[SizeParameter+1];
     //copy the contents strSourc
    for(int i=0; i<SizeParameter+1; i++)
    {
    *(p_start+i) = *(newtext+i);
    }
    return p_start;
  }
  char* operator=(const char* newtext)
  {
  AssignNewString(newtext);
  }
  };



 int main() 
 {
 String myString("Hello");  
 // Create object myString, send "Hello" string literal as argument
 std::cout << "string size: " << myString.m_size << std::endl;

 std::cout << myString.p_start << std::endl; 
// Prints "Hello"

*myString.p_start = 'Y'; 
// Attempt to change value at first byte of myString.p_start

std::cout << myString.p_start << std::endl; 
// Prints "Hello" (no change)

myString = "yellow"; 
// Assigning a string literal to p_start pointer 
myString = "THIS IS A LONGER STRING";

std::cout << myString.p_start << std::endl; 

std::cout << "string size: " << myString.m_size << std::endl;
return 0;
}

Note I am learning myself so do let me know if I am doing something wrong. But so far, it seems to work.

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172924

I think you're confusing about pointer and pointee.

p_start = "Yellow", you're changing the value of pointer, to point to "Yellow". *p_start = 'Y', you're changing the value of pointee, the content p_start points to, not itself. As you said, "Yellow" are const chars, so the behaviour try to modify them is UB.

You can make a copy of it in the ctor, then you can modify the chars, which are managed by the class. Yes, it will be a new copy, but it won't be a waste of memory. And you have no choice if you want them to be changable.

Upvotes: 1

Related Questions