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

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

我是一名大学生。我主要使用 Java,C++ 对我来说很新,所以我可能会犯很多愚蠢的错误,而且我还有即将到来的考试要应付。别对我太苛刻了。

注意:我不能使用 C++ std::string 因为我因为大学任务需要使用 C 字符串!

参考我的研究和我问的关于指针和 const 参数的问题(你会发现 )我试着搞乱内存管理但它似乎没有效果,或者我只是误解了某些方面 sizeof 或某些元素的实际大小。

这是我的 class 人:

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;
};

我试图通过创建一个字符串长度为给定参数的 C 字符串来节省内存。 认为 C 字符串是一个字符数组,节省字符会导致节省内存,例如"John" 的 C 字符串比 "Jonathan" 的 C 字符串占用更少的内存。

所以现在我不确定是我对 C 字符串或字符数组的概念有误,还是我的实现有问题。

在我的 main 中,我创建了以下对象:

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();
};

但是我总是得到每个对象 24 个大小,所以每个成员变量 8 个。这是为什么?

提前致谢。

我认为您期望 sizeof 运算符的行为与实际行为不同。让我们以这段代码为例:

const char* str = new char[137];

在这里,如果你写 sizeof(str) 你可能会得到 4 或 8,这取决于你的系统,因为 sizeof(str) 测量指针 str 本身的字节数而不是 str 指向的数组中的字节数。因此,在 32 位系统上,您可能会得到 4 个,而在 64 位系统上,您可能会得到 8 个,这与您分配的字符数无关。

不幸的是,C++ 没有办法让您获得字符数或动态分配的数组所用的内存。您只需要自己跟踪即可。

类似地,在您的主函数中,当您编写 sizeof(p) 时,您正在测量对象 p 使用的字节数,而不是 [=17] 使用的总字节数=] 和它指向的数组。 sizeof(p) 无论它指向什么字符串,你总是会得到相同的值。

如果您打算在 C++ 中使用字符串,我强烈建议您使用 std::string 而不是原始 C 风格的字符串。它们更容易使用,它们会记住它们的长度(因此更难混淆 strlensizeof),并且如果你有一个 class 持有 s 一堆 std::strings 您不需要复制构造函数或赋值运算符来处理将它们随机播放的逻辑。这将显着清理您的代码并消除其中的大部分内存错误。

sizeof 为您提供 c/c++ 将对象保存在内存中所需的字节数。在你的情况下(虽然你没有显示它)看起来 nameaddressphone 是指向 char:

的指针
struct Person {
  char *name, *address, *phone;
}

a pointer 是一个保存另一个对象地址的变量。因此,根据底层系统,它可能占用 32 位(4 字节)或 64 位(8 字节)(或其他数字)。在这种情况下,sizeof struct person 将用于 64 位系统 -- 24。(每 8 个字节有 3 个指针)。这对应于您的结果。

sizeof为您提供尺寸计算。您的字符串由那些指针指向,并且不包括它们的长度。因此,您可能需要创建一个成员函数来为您计算这些值,即

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

并且如之前评论中所述,c/c++ 中的每个 char *string 都必须有一个终止字符 ('\0'),它告诉程序字符串结束的位置。所以,如果你为一个字符串分配 space,你也应该为它提供 space(长度 + 1)。而且你必须确保这个字符写成'\0'。如果你使用库函数来复制字符串,它们会自动处理,否则你需要手动完成。

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 `[=12=]` to the end
 }

如果您使用循环而不是 strcpy 来复制字符,则需要手动添加:

    name[strlen(n)] = 0;