views:

351

answers:

7

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) {}
};

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...

+3  A: 

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

stefaanv
+1  A: 

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

stribika
+1  A: 

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
A: 

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
I am sure that this is not true any more.
David Allan Finch
I think this is probably up to the implementation
1800 INFORMATION
Wikipedia: "The string class provided by the C++ standard library, for example, was specifically designed to allow copy-on-write implementations."
Michal Czardybon
but many implementations don't because the need to provide some of the functionality - such as the non-const operator[] - mean the that gains are often not worth the cost.
Charles Bailey
Most importantly, COW is a pain in multi-threaded applications. The copy can happen at any moment.
MSalters
+6  A: 

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
Thanks, that's what I wanted to know.
milan1612
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.
tequilatango
+1  A: 

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
yes, `const char *` would be the best for constant-initialized strings, but it's not necessarily the case.
Michael Krelin - hacker
A: 

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.

larsm