2

I have a class whose constructor takes a const reference to a string. This string acts as the name of the object and therefore is needed throughout the lifetime of an instance of the class.

Now imagine how one could use this class:

class myclass {
public:
    myclass(const std::string& _name) : name(_name) {}
private:
    std::string name;
};

myclass* proc() {
    std::string str("hello");
    myclass* instance = new myclass(str);
    //...
    return instance;
}

int main() {
    myclass* inst = proc();
    //...
    delete inst;
    return 0;
}

As the string in proc() is created on the stack and therefore is deleted when proc() finishes, what happens with my reference to it inside the class instance? My guess is that it becomes invalid. Would I be better off to keep a copy inside the class? I just want to avoid any unneccessary copying of potentially big objects like a string...

Milan
  • 3,342
  • 3
  • 31
  • 40
  • the `name` member of your class is not declared. – xtofl Sep 10 '09 at 09:47
  • and it's invalid to start identifiers with an underscore: these identifiers are reserved for your compiler and it's libraries (e.g. `__FILE__`, `_fstat`, ...) – xtofl Sep 10 '09 at 09:49
  • xtofl, I had no idea this convention made it into standards! Thanks, that was nice to learn. – Michael Krelin - hacker Sep 10 '09 at 09:54
  • Didn't know of this standard, g++ does not complain about it even with -Wall -Weffc++. Oh well ;-) – Milan Sep 10 '09 at 09:59
  • that's not *quite* true - see here for the chapter and verse http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – 1800 INFORMATION Sep 10 '09 at 10:03
  • As far as I know you aren't storing a reference here: `name(_name)` invokes the copy-constructor, i.e. name is generated by copying _name. – fishbone Apr 22 '12 at 20:52

7 Answers7

8

Yes, Reference becomes invalid in your case. Since you are using the string it is better to keep a copy of the string object in myclass class.

aJ.
  • 34,624
  • 22
  • 86
  • 128
  • Thanks, that's what I wanted to know. – Milan Sep 10 '09 at 10:01
  • And keeping that copy is cheap, because std::string is (usually) implemented as a reference counted object, so you don't actually copy the string data, just extend it's life time. – Teemu Kurppa Sep 10 '09 at 13:10
3

By all means: copy. Have a "std::string name" member in your class. It's the only way to control the life-time.

stefaanv
  • 14,072
  • 2
  • 31
  • 53
1

If myclass::_name is not a reference then it is copied and will not become invalid.

stribika
  • 3,146
  • 2
  • 23
  • 21
1

You don't have to do copying. Declare std::string name (not reference) member in myclass (which you somehow omitted altogether). and pass const char * as an argument. This way you will construct your name object right in the class with no copying.

class myclass {
public:
    std::string name;
    myclass(const char *_name) : name(_name) { }
};

myclass *proc() {
    return new myclass("hello");
}
Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
1

Yes the std::string will disappear but the c str "hello" will not as it is a constant.

You have two possible answers. Use the c str as a reference or make the std:string a staic.

David Allan Finch
  • 1,414
  • 8
  • 20
0

The field myclass::name should be of type std::string. Strings in C++ are copied-on-write (http://en.wikipedia.org/wiki/Copy-on-write) so you don't get problems with copying of big objects.

Michal Czardybon
  • 2,795
  • 4
  • 28
  • 40
0

Keep a copy of the string in MyClass, keeping a reference is definitively not safe. If you expect a lot of instances to have the same name, you should look into the Flyweight design pattern which allows to save storage when you have a lot of equal instances. Boost.Flyweight is a very conventient implementation of this pattern that allows you to simply write:

class myclass {
public:
    myclass(const std::string& _name) : name(_name) {}
private:
    boost::flyweight<std::string> name;
};

Some implementations of std::string may do this behind the scene, but it is not required. You should therefor not rely on this.

larsmoa
  • 12,604
  • 8
  • 62
  • 85