简体   繁体   English

C ++ sizeof C风格的字符串/ char数组-优化

[英]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. 我主要使用Java,C ++对我来说还是很新的,所以我可能犯了许多愚蠢的错误,并且我即将进行考试。 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! 注意:我不能使用C ++ std :: string,因为由于大学工作,我需要使用C字符串!

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. 关于我的研究以及我问到的有关指针和const参数的问题(您可以在此处找到),我尝试弄乱内存管理,但似乎没有任何效果,或者我只是误解了某些元素的sizeof或实际大小的某些方面。

This is my class Person: 这是我班的人:

Person.cpp 人.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. 我试图通过使用给定参数的字符串长度创建C字符串来节省内存。 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". 认为C字符串是一个char数组,保留char会导致保留内存,例如,“ John”的C字符串比“ Jonathan”的C字符串占用更少的内存。

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. 所以现在我不确定是否只是对C字符串或char数组的概念有误,还是我的实现是错误的。

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. 但是我每个对象的大小都是24,所以每个成员变量的大小是8。 Why is that? 这是为什么?

Thanks in advance. 提前致谢。

I think you are expecting the sizeof operator to behave differently than it actually does. 我认为您期望sizeof运算符的行为与实际不同。 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 . 在这里,如果您写sizeof(str) ,则可能会得到4或8,这取决于您的系统,因为sizeof(str)测量指针str本身的字节数,而不是所指向的数组中的字节数。通过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. 因此,在32位系统上,您可能会得到4,而在64位系统上,您可能会得到8,而与分配的字符数无关。

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. 不幸的是,C ++无法让您获得动态分配的数组所占用的字符数或内存。 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. 同样,在您的main函数中,当您写入sizeof(p) ,您正在测量对象p使用的字节数,而不是p及其指向的数组的总字节数。 You'll always get back the same value for sizeof(p) regardless of what strings it points at. 无论它指向什么字符串,都将始终获得相同的sizeof(p)值。

If you're planning on working with strings in C++, I strongly recommend using std::string over raw C-style strings. 如果您打算在C ++中使用字符串,我强烈建议您在原始C样式字符串上使用std::string 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. 它们更易于使用,记住它们的长度(因此很难混合strlensizeof ),并且如果您有一个类持有一堆std::string ,则不需要复制构造函数或赋值运算符处理逻辑以将其洗牌。 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. sizeof为您提供了c / c ++将对象保存在内存中所需的字节数。 In you r case (though you have not shown it) it looks like name , address , and phone are pointers to char: 在您的情况下(尽管您没有显示),它看起来像nameaddressphone是指向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). 因此,根据底层系统的不同,它可能占用32位(4个字节)或64位(8个字节)(或其他一些数字)。 In this case the sizeof struct person will be for 64-bit system -- 24. (3 pointers per 8 bytes each). 在这种情况下,struct person的大小将用于64位系统-24。(每8个字节3个指针)。 This corresponds to your results. 这与您的结果相对应。

The sizeof provides you with a shallow size calculation. sizeof为您提供了较浅的尺寸计算。 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. 就像前面的评论中提到的那样,c / c ++中的每个char *string都必须有一个终止字符('\\ 0'),该字符告诉程序字符串在何处结束。 So, if you allocate space for a string, you should provide space for it as well (+ 1 to the length). 因此,如果为字符串分配空间,则还应为其提供空间(长度加1)。 And you have to make sure that this character is written as '\\0'. 并且您必须确保此字符写为'\\ 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: 如果使用循环来复制字符而不是strcpy ,则需要手动添加它:

    name[strlen(n)] = 0;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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