-1

I'm a student at university. I work mostly with Java, C++ is very new to me, so I probably make many silly mistakes and I have upcoming exams to cope with. Don't be too harsh with me.

Note: I can NOT use C++ std::string because I need to work with C-strings due to university tasks!

Referring to my studies and the question I asked about pointers and const arguments (which you find here) I tried messing around with memory management but it seems it has no effect, or I just misunderstood some aspects about sizeof or actual sizes of certain elements.

This is my class Person:

Person.cpp

using namespace std;

Person::Person()
{
    Person::name = new (char[64]);
    Person::adress = new (char[64]);
    Person::phone = new (char[64]);

    cout << "standard constructor called; object created, allocated " << sizeof(name) << "+" << sizeof(adress) << "+" << sizeof(phone) << "bytes" << endl;

}

Person::Person(const char *name, const char *adress , const char *phone)
{

    Person::name = new (char[strlen(name)]);
    Person::adress = new (char[strlen(adress)]);
    Person::phone = new (char[strlen(phone)]);


    setName(name);
    setAdress(adress);
    setPhone(phone);

    cout << "general constructor called; object created, allocated " << sizeof(this->name) << "+" << sizeof(this->adress) << "+" << sizeof(this->phone) << "bytes" << endl;
};

Person::Person(Person const &other)
{

    Person::name = new (char[strlen(other.getName())]);
    Person::adress = new (char[strlen(other.getAdress())]);
    Person::phone = new (char[strlen(other.getPhone())]);


    setName(other.getName());
    setAdress(other.getAdress());
    setPhone(other.getPhone());

    cout << "copy constructor called; object created, allocated " << sizeof(name) << "+" << sizeof(adress) << "+" << sizeof(phone) << "bytes" << endl;
};

Person::~Person()
{
    delete [] name;
    delete [] adress;
    delete [] phone;

    cout << "destructor called; object removed" << endl;
};

I tried to spare memory with creating a C-string with a string length of the given parameters. Thinking that a C-string is a char array, sparing chars would result in sparing memory, e.g. a C-string of "John" takes up less memory than a C-string of "Jonathan".

So now I'm not sure if I just got the wrong concept of C-strings or char arrays, or my implementation is just faulty.

In my main I create the following objects:

int main()
{
    Person t;
    t.printPerson();

    cout << "size of t: " << sizeof(t) << endl;

    Person p("John", "some street", "0736182");
    p.printPerson();

    cout << "size of p: " << sizeof(p) << endl;

    Person x(p);
    x.printPerson();

    cout << "size of x: " << sizeof(x) << endl;

    Person y("Jonathan", "Lancaster Ave 53", "3584695364");

    y.printPerson();

    cout << "size of y: " << sizeof(y) << endl;

    cin.get();
};

But I alwas get a size of 24 per object, so 8 for each member variable. Why is that?

Thanks in advance.

GenerationLost
  • 179
  • 1
  • 1
  • 15
  • 2
    Your object contains 3 pointers, what is the size of 3 pointers? – NathanOliver Jul 20 '17 at 14:05
  • and the cstring needs a '\0' char. "John" + '\0' – Captain Giraffe Jul 20 '17 at 14:06
  • 1
    side note: you should allocate each string buffer with length `strlen + 1`, adding 1 for the zero terminating character – meowgoesthedog Jul 20 '17 at 14:06
  • 2
    Of course using std::string would relieve you of your troubles, but I suppose you are looking for trouble. – Captain Giraffe Jul 20 '17 at 14:08
  • 2
    An array is not a string is not a pointer. – too honest for this site Jul 20 '17 at 14:08
  • `sizeof` is a _compile time_ operator. It cannot tell the _run time_ size of a dynamically allocated object, such as with `new(char[strlen(name)+1])`. – Paul Ogilvie Jul 20 '17 at 14:09
  • Allocating the array in the constructor and the deleting it and allocating it again in the setter does not seem thought through....Especially with calling strlen again and again.... – Simon Kraemer Jul 20 '17 at 14:11
  • 150 lines of code? Read [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) – molbdnilo Jul 20 '17 at 14:18
  • @molbdnilo every time I provide a "minimal" example I have to post the whole code anyway because some things aren't clear enough... – GenerationLost Jul 20 '17 at 14:44
  • @NathanOliver oh, really didn't see that... C++ is giving me hell of a time, thank you – GenerationLost Jul 20 '17 at 14:44
  • @CaptainGiraffe thanks for the hint, can't use C++ strings tho bc it's related to my studies and exams – GenerationLost Jul 20 '17 at 14:44
  • @PaulOgilvie then how can I get the sizes at run time? and how do I get the size of the char array the pointer is pointing to? – GenerationLost Jul 20 '17 at 14:44
  • Use `strlen(c_string) + 1`, you logic is based on that assumption. You can't get the size of pointed to array from the pointer itself. – Captain Giraffe Jul 20 '17 at 14:49
  • Does it spare memory now or is all of that useless? – GenerationLost Jul 20 '17 at 14:51
  • Compared to a std::string, not really. Compared to fixed-size `char name[2048]`, yes a little bit. The scenario is unrealistic and archaic though. – Captain Giraffe Jul 20 '17 at 14:55
  • There are many issues. I'd suggest to get some C++ book and start reading it from the beginning – Jabberwocky Jul 20 '17 at 14:59
  • C++ is **NOTHING** like Java. Nothing. Stop using `new`, forget everything you know about Java and get [a good C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list?lq=1). Nothing you know about Java applies to C++. They are cosmetically similar and nothing more. – Rob K Jul 20 '17 at 15:09
  • 1
    @RobK gee I see myself that it's definitely not the same, that's why I'm having all these issues, alright? and I only do those things I'm being taught at university 'cause that's what I need for my exams... I will read a book about C++ programming, but in my free time and when I'm off university, but for now I simply just needed some answers to my "special" issues here, since I can't just go to my prof and be like "yo bro this is bullshit I'd rather use this n that" just to fail my exam in the end – GenerationLost Jul 20 '17 at 15:15

2 Answers2

3

I think you are expecting the sizeof operator to behave differently than it actually does. Let's take this code, for example:

const char* str = new char[137];

Here, if you write sizeof(str) you'll probably either get 4 or 8, depending on your system, because sizeof(str) measures the number of bytes of the pointer str itself rather than the number of bytes in the array pointed at by str. So, on a 32-bit system, you'd probably get 4, and on a 64-bit system you'd probably get 8, independently of how many characters you allocated.

Unfortunately, C++ doesn't have a way for you to get the number of characters or the memory used up by a dynamically allocated array. You just have to track that yourself.

Similarly, in your main function, when you write sizeof(p), you're measuring the number of bytes used by the object p, not the total number of bytes used by p and the arrays it points at. You'll always get back the same value for sizeof(p) regardless of what strings it points at.

If you're planning on working with strings in C++, I strongly recommend using std::string over raw C-style strings. They're much easier to use, they remember their length (so it's harder to mix up strlen and sizeof), and if you have a class holding s bunch of std::strings you don't need a copy constructor or assignment operator to handle the logic to shuffle them around. That would significantly clean up your code and eliminate most of the memory errors in it.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    I think OP has requirements from an assignment that explicitly prohibits std::string. OP: - "thanks for the hint, can't use C++ strings tho bc it's related to my studies and exams" – Captain Giraffe Jul 20 '17 at 15:08
  • Just like Captain Giraffe wrote, but thank you so much for a very useful and polite answer! I'd give this an upvote, if all those downvotes on this question (for reasons I really don't get, all I asked for is help for this speciffic case) wouldn't have sent my reputation to hell... – GenerationLost Jul 20 '17 at 15:20
  • @GenerationLost I suspect that people have downvoted this question because it has been asked and answered in a number of variations for years on stackoverflow. It is one of several of these kinds of questions where people who have been on the site and using the site for years are just tired of seeing it come up over and over and over again. – Richard Chambers Jul 20 '17 at 15:58
  • @RichardChambers Then why not just ignoring it or referring to these questions? I percieve it as rather rude to downvote someone in need of help. I always search the Internet first before I ask questions and since I found nothing that really helped me in my case it' kinda discouraging to ask anyway and then get somehow punished for that... But I guess that's just off-topic now, so I better save myself from even more downvotes, huh... – GenerationLost Jul 20 '17 at 16:06
  • 1
    @GenerationLost from their perspective cluttering up the site with the same questions is rather rude as well. What happens is that the people who can answer good, unusual questions on topics that are intermediate to advanced end up getting discouraged seeing the same beginner questions time after time. So they pay less attention to questions which in turn hurts people with questions that are not easy to answer from a search on the internet and some critical thinking. You mention university and I wonder why either your classmates or professor were unable to help. Also see Peer Pressure badge. – Richard Chambers Jul 20 '17 at 17:44
1

sizeof gives you a number of bytes which c/c++ need to keep the object in memory. In you r case (though you have not shown it) it looks like name, address, and phone are pointers to char:

struct Person {
  char *name, *address, *phone;
}

a pointer is a variable which keeps an address of another object. So, depending on the underlying system it could occupy 32 bits (4 bytes) or 64 bite (8 bytes) (or some other number). In this case the sizeof struct person will be for 64-bit system -- 24. (3 pointers per 8 bytes each). This corresponds to your results.

The sizeof provides you with a shallow size calculation. Your strings are pointed by the those pointers and their lengths are not included. So, potentially you need to create a member function which will calculate those for you, i.e.

struct Person {
   char *name, *address, *phone;
   int getSize() {
      return strlen(name) + strlen(address) + strlen(phone);
   }
};

And as mentioned in the comments before, every char *string in c/c++ must have a termination character ('\0') which tells the program where the string ends. So, if you allocate space for a string, you should provide space for it as well (+ 1 to the length). And you have to make sure that this character is written as '\0'. if you use library functions to copy strings, they will take car of it, otherwise you need to do it manually.

void setName(const char *n) {
  name = new char[strlen(n) + 1]; // includes needed '0', if exists in 'n'
  strcpy(name, n); // copies the string and adds `\0` to the end
 }

If you use the loop to copy chars instead of strcpy you would need to add it manually:

    name[strlen(n)] = 0;
Serge
  • 11,616
  • 3
  • 18
  • 28
  • `"In you r case (though you have not shown it) ... "` I removed the header bc some people complained about my code length... Anyway, thanks for your kind explanation and your examples, it was very helpful! – GenerationLost Jul 20 '17 at 15:27