简体   繁体   中英

C++ sizeof C-style string / char array - optimization

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

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::string s 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.

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, ie

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM