Building string class

Greetings,

A friend of mine is Learning C++ and he was given the assignment to create a String class that would implement constructor copy and '+' and '=' overloading without modifying the strings, i.e a = b means a and b both point to the same char*. The difficulty resides in making sure that doing c = b and then deleting a does not modify either b or c.

Apparently,a trick is to keep a pointer to the number of instances of string that point to the same string. But my friend gets unusual results at the end of his program so I thought perhaps somebody might be able to help a little more than I was.

Anyways, here's his implementation. + overloader isn't in there yet.

Main class :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include "stack.h"
#include "newstring.h"

using namespace std;

int main()
{
       char* BLABLA = "blabla";

    Newstring s(BLABLA,7);
 cout << "s : " << endl;
    s.printS();
    Newstring t(s);
    t.printS();

    s.~Newstring();
    t.printS();
    t.~Newstring();
return 0;
}


Newstring cpp class :
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
#include "newstring.h"
#include <iostream>
using namespace std;

Newstring::Newstring(char* const& c, int l){
length = l;
chars = new char[l+1]; 
for(int i = 0; i < l; i++){
    chars[i] = c[i];
}
nbref=new int(1);
*nbref = 1;
}

Newstring::Newstring(Newstring const& s){
    chars = s.chars;
    nbref = new int(1);
    (*s.nbref)++;
    nbref =  s.nbref;
    cout << "original.nbref : " <<*s.nbref << " copy.nbref "  << *nbref << endl;
}

Newstring& Newstring::operator=(Newstring& s){
if(&s != this){
    delete[] &chars; // Incorrect ?
    chars = s.chars;
}
return *this;
}

Newstring::~Newstring(){
    //cout << nbref;
    cout << *nbref << endl;
    if(*nbref == 0){
            delete[] chars;
    }else{
        *nbref--;
        cout << "decr ref : " << *nbref << endl;
        }
    delete &chars;};

void Newstring::printS(){
cout << chars << endl << " number refs : " << *nbref << " " << endl;
}



Newstring header
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED

class Newstring{
public :
    Newstring(char* const& c, int l);
    Newstring(const Newstring& s);
    Newstring& operator=(Newstring& s);
    ~Newstring();
    void printS();

private :
    char* chars;
    int length;
    int* nbref;
};

#endif // Newstring_H_INCLUDED 
Reference counting, shared pointer, copy-on-write strings.

Make a struct Foo that has data in char* and a size_t counter. Make Newstring have one Foo*. Update counter when necessary. If counter hits 0, call delete.

Newstring is interface. Foo is hidden implementation. You can use pimpl idiom for extra fun.
Hmm, I don't think that's detailed enough. Besides, I think the code is almost correct, and doesn't need to be modified that much, and that it is more to the point of the assignement to stay true to its guidelines.

The string doesn't delete when the destructor is called, which is good, however the nbref variable behaves strangely. Sorry, probably should have been clearer about this.

Edit : I see what you mean, but is it really necessary to have such a struct ?
Last edited on
Topic archived. No new replies allowed.