C++,为什么我没有得到值"123456"

C++ , how come I do not get the value "123456"

本文关键字:123456 为什么 C++      更新时间:2023-10-16

我正在尝试打印出值123456,但它给了我垃圾值。我该如何解决它?你能解释一下为什么它给出了错误的值吗?

#include <stdio.h>
#include <stdlib.h>
struct MyInfo
{
private:
int private_key = 123456;
public:
int setkey(int value)
{
private_key = value;
}
int GetScore()
{
return private_key;
}
};
void main()
{
MyInfo* pMyInfo;
pMyInfo = (MyInfo*)malloc(sizeof(MyInfo));
printf("%dn",  pMyInfo->GetScore());
free(pMyInfo);
}

不要使用malloc/free,而是使用pMyInfo = new MyInfo()delete pMyInfo。只有new会调用初始化值的构造函数;只有delete会调用析构函数。

关于注释,意思是,您也可以将其放在堆栈上,即MyInfo pMyInfo;,即不是指针。这将自动调用构造函数,当它超出范围时,将自动调用析构函数。

int private_key = 123456;

这实际上只是一个伪装的构造函数初始化,这意味着它与:

MyInfo() : private_key(123456) {}

由于malloc和友元是从 C 继承而来的,而 C 没有类(因此没有特殊的成员函数(,因此malloc和朋友不会调用这些必要的特殊成员函数来设置你的对象。但是,C++等效的new这样做,这就是为什么您应该始终使用new而不是mallocdelete而不是free


但是等等,还有更多...

实际上,您也不应该使用new,总有比使用原始动态分配更好的选择。如果您确实需要动态内存分配,请使用std::unique_ptr或多个对象std::vector但大多数时候您甚至不需要这些(这里有大量的帖子解释了何时必须进行动态分配,对于所有其他情况,只需使用具有自动生命周期的存储(在这种情况下,您只需要一个本地对象:

MyInfo myInfo;
printf("%dn",  myInfo.GetScore());

看看您的代码如何变得更短、更易于维护和更简洁,以实现相同的目标?

当你声明一个 MyInfo 类型的指针时,这并不意味着它指向的对象实际上是你的结构,它只是假设它会是。

当你做malloc(sizeof(MyInfo))时,你只是分配你的结构可能占用的大小的内存,它不会创建一个对象。因此,当你尝试做GetScore()时,它会访问内存位置,它假设包含你的private_key,但它只是包含垃圾。

不要CC++混为一谈

您应该避免C++malloc/alloc等,如果要使用动态分配的对象new请选择运算符。

添加构造函数以初始化值

private;
int private_key;
public:
MyInfo () {
private_key = 123456;
}

并实现主要喜欢

// without pointer
void main () {
MyInfo myinfo;
printf("%dn", myinfo.GetScore());
}
// with pointer
void main () {
MyInfo *myinfo = new MyInfo();
printf("%dn", myinfo->GetScore());
}

仅供参考,可以在原始存储中初始化对象,但对于此用例而言,这将是矫枉过正且相当愚蠢的。由于 malloc 只分配原始内存而不构造对象,因此您可以使用 new 放置来第二次构建对象:

int main()      // I can't stand void main
{
MyInfo* pMyInfo;
pMyInfo = (MyInfo*)malloc(sizeof(MyInfo));  // only allocate raw memory
new((void *) pMyInfo) MyInfo;               // construct the object
std::cout << pMyInfo->GetScore() << std::endl;  // no reason for C printf here
pMyInfo->~MyInfo(); // placement new requires explicit destructor call if not trivial
free(pMyInfo);
return 0;
}

对于如此简单的情况,不要这样做。放置新应仅在分配不平凡的非常特殊的情况下使用,例如,当您使用共享内存时。但这里正确的方法是简单地使用自动对象:

int main()      // I can't stand void main
{
MyInfo pMyInfo;
std::cout << pMyInfo.GetScore() << std::endl;
return 0;
}