Milan
Milan

Reputation: 3370

C++ reference in constructor

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

Upvotes: 2

Views: 7587

Answers (7)

larsmoa
larsmoa

Reputation: 12942

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.

Upvotes: 0

David Allan Finch
David Allan Finch

Reputation: 1424

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.

Upvotes: 1

aJ.
aJ.

Reputation: 35490

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.

Upvotes: 8

Michal Czardybon
Michal Czardybon

Reputation: 2865

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.

Upvotes: 0

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143279

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

Upvotes: 1

stribika
stribika

Reputation: 3176

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

Upvotes: 1

stefaanv
stefaanv

Reputation: 14392

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

Upvotes: 3

Related Questions