8

I'm new to and learning C++. I know a fair amount of Java and some C.

What I want to do is to create an immutable name class that takes in a string value, copies that string to a class field and then eventually hashes it to an ID that can be parsed much more efficiently than a string.

I'm hitting a wall due to a general lack of knowledge of C++ strings. Here's what I have so far...

#pragma once

#include <string>

class Name
{
public:
    Name(std::string s);
    ~Name(void);

    int getId();
    std::string getName();

private:
    int id;
    std::string name;
};

and...

#include "Name.h"

Name::Name(std::string s)
{

}

So what I want to do is store the value of s, passed in by the constructor in the "name" private field. As far as I know a new string object must be created and then the value of s must be copied into it.

I also think that the argument s can and should be a string pointer instead of a string object (to prevent an unnecessary copy from occurring). If I'm right then the constructor should look like the following, right?

Name::Name(std::string &s) { ... }

In this case, nothing would need to be done special when passing in a name? IE.

Name n = new Name("Cody");

is perfectly valid? Actually I'm not sure since "Cody" to my knowledge is a constant string or something like that.

So if I'm all on the right track, then what is the proper way to actually copy the value? I'm thinking this is appropriate but I'm not sure.

#include "Name.h"

Name::Name(std::string s)
{
    name = new string(s);
}

Thanks for the help in advance, I know it's a basic question but I'm slowly making baby steps into the C++ world. :) - Cody

Cody Smith
  • 2,732
  • 3
  • 31
  • 43
  • 4
    `Name::Name(const std::string &s) : name(s){}` Also, in there, `s` is a reference, not a pointer. – chris Dec 23 '12 at 03:10
  • Ah I understand, this takes in the address of a constant string and hands it off to the name field using an initialization list? If I'm right no copy is executed, name just points to the address of s? – Cody Smith Dec 23 '12 at 03:20
  • 1
    Almost, but it's not a pointer, it's a reference. You can see [this](http://stackoverflow.com/questions/57483/what-are-the-differences-between-pointer-variable-and-reference-variable-in-c) for the differences. It takes in the string itself, not the address. `name` gets a copy of `s`. – chris Dec 23 '12 at 03:21

2 Answers2

3

You are close, your code can be like this after a little massage:

class Name
{
public:
    Name(const std::string& s);  // add const and reference
    ~Name(void);

    int getId() cosnt;           // add const
    std::string getName() const; // add const

private:
    int id;
    std::string name;
};

Name.cpp

Name::Name(const std::string& s):name(s)
{
}

Here :name(s) is called member initializer list.

Name n = new Name("Cody"); is perfectly valid? Actually I'm not sure since "Cody" to my knowledge is a constant string or something like that.

No, n is not pointer, it's not like java you need to new for every object. In C++, you do

Name n("Cody");

This will call Name(const std::string& s) to initialize object n and initialize name string with "Cody". Note: variable n has automatic storage duration, it will be destroyed if it goes out of scope.

To let n on dynamic storage duration, you need to use new/delete pair:

 Name *pn = new Name("Cody");
 delete pn;

or use smart pointers, you no need to call delete n_ptr; as n_ptr will be destroyed when it goes out of scope as well:

 #include <memory>
 std::shared_ptr<Name> n_ptr(new Name("Cody"));

EDIT:

To use Name class in other classes, it's the same way when you use string in Name class, you don't have to use pointers.

class TestName
{
public:
   TestName(const Name& n):name_(n){ }

private:
  Name name_;
};

TestName tn("Cody");
billz
  • 44,644
  • 9
  • 83
  • 100
  • Oh wow. So only use new when assigning a pointer to a new object? – Cody Smith Dec 23 '12 at 03:30
  • 1
    @CodySmith, Yes, but in that case, prefer a smart pointer instead. It manages the memory for you, so you don't have to delete it yourself. – chris Dec 23 '12 at 03:31
  • Thanks. I am acquainted with at least the idea behind smart pointers (reference counting), I can thank Java for that. So I have to ask, this Name class will end up being a field inside other classes that will be dynamically created. I'm guessing since other classes containing a Name object will have to use a object pointer then they will call new Name() and delete Name() in their constructor/deconstructor? – Cody Smith Dec 23 '12 at 03:40
1

You should use a constant reference to std::string here.

As you said, it would prevent unnecessary copies.. But then why not just a pointer or a constant pointer?

A constant reference would allow you to pass to your function some arguments that would implicitly call the right std::string constructor.

So, in a nutshell, you could do that:

Name::Name(const std::string& s)
{
    this->name = s;
}

// Or even better..
Name::Name(const std::string& s):
    name(s)
{
}

int    main(void)
{
    Name    nick("hello");

    return 0;
}

You can find out about every std::string's constructors on its cplusplus.com's sheet.

cmc
  • 2,061
  • 1
  • 19
  • 18
  • So when the Name object is destroyed I should probably call delete on the name field when the Name object in the deconstructed? – Cody Smith Dec 23 '12 at 03:24
  • 1
    You did not dynamically allocate your object Name, nor did you allocate your std::strings. There is nothing to delete manually here! – cmc Dec 23 '12 at 03:27
  • 2
    @CodySmith if you really want to bite into using the standard library and C++ with proper memory management ideology, take most of what you learned about pointers and memory management in C and throw it out the window. I *highly* recommend [this presentation](http://dl.dropbox.com/u/6101039/Modern%20C%2B%2B.pdf) if you want to see examples of how you should think about many old ideas in a new frame of light. – WhozCraig Dec 23 '12 at 03:30
  • Thanks so much Whoz, it's looking like many of the styles I am accustomed to using in Java and C need to be properly shelved. This has all been highly informative. I will read that presentation very soon. Thx again. – Cody Smith Dec 23 '12 at 03:34