In rm_space method s is unchanged after function calls. Why?
Because s is passed by value. In other words - it's not the variable s that is passed but the value that s holds. The variable s in the called function and the variable s in the calling function are two different variables. Consequently, changes made to one of them does not change the other.
If you want to change s in the calling function inside the called function, you need to use call-by-reference.
Something like:
void MyString::rm_left_space(char*& s){
However, notice that your code have a major problem as it seems you are trying to assign s2 in the called function to s in the calling function. You should never do that as s2 goes out of scope as soon as the function returns.
Example: Difference between pass-by-value and between pass-by-value
This simple program uses pass-by-value
#include <iostream>
void foo(int x)
{
  x = 42;
  std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
  int x = 21;
  std::cout << "Before foo: x=" << x << std::endl;
  foo(x);
  std::cout << "After foo: x=" << x << std::endl;
  return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=21    // notice x didn't change
because x in foo and in main are two different variables.
This simple program uses pass-by-reference
#include <iostream>
void foo(int& x)   // Notice the &
{
  x = 42;
  std::cout << "Inside foo: x=" << x << std::endl;
}
int main()
{
  int x = 21;
  std::cout << "Before foo: x=" << x << std::endl;
  foo(x);
  std::cout << "After foo: x=" << x << std::endl;
  return 0;
}
The output is
Before foo: x=21
Inside foo: x=42
After foo: x=42   // notice that x changed
because now x inside foo is a reference to x in main
These examples used int but exactly the same applies for pointers.
Example: Using pointers
#include <iostream>
int x = 21;
int y = 5;
void foo(int* p)
{
  *p = 42;
  p = &y;
  std::cout << "Inside foo:  p = " << p << std::endl;
  std::cout << "Inside foo: *p = " << *p << std::endl;
}
int main()
{
  int* p = &x;
  printf("%p\n", (void*)p);
  std::cout << "Before foo:  p = " << p << std::endl;
  std::cout << "Before foo: *p = " << *p << std::endl;
  foo(p);
  std::cout << "After foo :  p = " << p << std::endl;
  std::cout << "After foo : *p = " << *p << std::endl;
  return 0;
}
Output:
Before foo:  p = 0x60106c
Before foo: *p = 21
Inside foo:  p = 0x601070
Inside foo: *p = 5
After foo :  p = 0x60106c  // Pointer value did NOT change
After foo : *p = 42        // Pointed to value DID change
Replacing
void foo(int* p)
with
void foo(int*& p)
will give:
Before foo:  p = 0x60106c
Before foo: *p = 21
Inside foo:  p = 0x601070
Inside foo: *p = 5
After foo :  p = 0x601070  // Pointer value DID change
After foo : *p = 5         // Consequently, the pointed to value also changed