Al netto di controllo errori e altri metodi (tipo operator= comunque necessario), intendo qualcosa del genere.
codice:
class Foo {
    public:
        Foo() {}
        Foo(const char* str);
        Foo(const Foo& other);
        ~Foo();
   private:
       char* ptr;
       
};

inline Foo::Foo() : ptr(nullptr) {}

inline Foo::Foo(const char* str) : ptr(nullptr) {
    ptr = new char[strlen(str)+1];
    strcpy(ptr,str);
}

inline Foo::Foo(const Foo& other) : ptr(nullptr) {
    ptr = new char[strlen(other.ptr)+1];
    strcpy(ptr,other.ptr);
}

inline Foo::~Foo() {
   delete [] ptr;
}
//---
int main(/* etc */) {
    Foo foo = Foo("ciao mondo");
    // ma non 
    Foo foo1("ciao mondo);
    Foo foo2;
    foo2 = foo1; // QUI non è invocato il costruttore di copia ma l'operatore di assegnamento.
}