Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy string value into a class field?

Tags:

c++

string

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

like image 507
Cody Smith Avatar asked Dec 23 '12 03:12

Cody Smith


2 Answers

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");
like image 107
billz Avatar answered Sep 21 '22 13:09

billz


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.

like image 24
cmc Avatar answered Sep 21 '22 13:09

cmc