Returning a pointer to char

Jul 20, 2017 at 6:59pm
I have a class that looks like:

class xxxx

private:
char * firstname[20];


public:

const char* getFirstName();



When constructing the "getFirstName" member function, I can't just do "return *firstname"

What is the proper syntax? Is a better design to just change it into "const string getFirstName();"?
Jul 20, 2017 at 7:12pm
Ignoring the issue of getFirstName for a moment:

firstname is an array of 20 pointers-to-char. I don't think that's what you intended.

Jul 20, 2017 at 7:13pm
First off, char * firstname[20]; is an array of 20 pointers, not an array of 20 characters. Get rid of the *.
 
char firstname[20];


I can't just do "return *firstname"

Again, get rid of the *.
 
return firstname;


Is a better design to just change it into "const string getFirstName();"?

Yes.

Last edited on Jul 20, 2017 at 7:13pm
Jul 22, 2017 at 1:38pm
Is a better design to just change it into "const string getFirstName()
Not quite.

This creates a separate const string each time you call it. If you're returning a separate string, then why say that the caller can't change it?

On the other hand, if someone just wants to read the first name, then why return a separate string at all?

And this won't work:
1
2
3
4
5
6
void f(const XXX &instance)
{
    string first;
    ...
    first = instance.getFirstName();   // Calling non-const method of const object
}


A much more common method is:
1
2
3
4
private:
string firstName;
public:
const string &getFirstName() const;

firstName is a string, so you don't have to worry about overflowing a buffer.

getFirstName() returns a const reference to the string. By returning a reference, you aren't making a copy of the string. By making the reference const, you prevent the caller from changing the underlying string (at least they can't without some casting gymnastics). Finally, my making the method itself const, you say that it can be called on a const object.
Jul 22, 2017 at 2:51pm
Here are four different versions (and more variations are possible)
Think about it, and choose one that is the most appropriate for the specific use case.
Hint: when in doubt, favour xxxx_3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class xxxx_1
{
    // may not be so good; the fixed size for a name is not very flexible
    // good: standard layout type, trivially copyable etc.
    static constexpr std::size_t NAMESZ = 20 ;
    char fname[NAMESZ] {} ;
    // ...

    public:
        // not so good; unencapsulated interface exposes the implementation
        //              (change in implementation may break the interface)
        constexpr const char* first_name() const { return fname ; }

        // ...
};

class xxxx_2
{
    // may not be so good; the fixed size for a name is not very flexible
    // good: standard layout type, trivially copyable etc.
    static constexpr std::size_t NAMESZ = 20 ;
    char fname[NAMESZ] {} ;
    // ...

    public:
        // good; encapsulated interface does not expose the implementation
        std::string first_name() const { return fname ; }

        // ...
};

class xxxx_3 // favour this as the default choice
{
    // good, flexible size for name
    std::string fname ;
    // ...

    public:
        // good; encapsulated interface does not expose the implementation
        std::string first_name() const { return fname ; }

        // ...
};

class xxxx_4
{
    // good, flexible size for name
    std::string fname ;
    // ...

    public:
        // not so good, un-encapsulated interface exposes the implementation
        //              (change in implementation would break the interface)
        // however, the performance would be better (avoid copying the string)
        //              (in general, treat performance as a constraint rather than a goal;
        //               so do this if and only if this performance improvement is a requirement)
        const std::string& first_name() const { return fname ; }

        // ...
};
Topic archived. No new replies allowed.