gpt4 book ai didi

c++ - 复制构造函数 : When storage is freed?

转载 作者:行者123 更新时间:2023-11-30 00:56:35 29 4
gpt4 key购买 nike

给定代码:

class Sample
{
public:
int *ptr;
Sample(int i)
{
ptr = new int(i);
}
~Sample()
{
delete ptr;
}
void PrintVal()
{
cout << "The value is " << *ptr;
}
};
void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}
int main()
{
Sample s1= 10;
SomeFunc(s1);
s1.PrintVal();
}

输出是:

Say i am in someFunc
Null pointer assignment(Run-time error)

我不明白为什么会出现第二行输出。输出的第二行。我认为编译器在未明确指定时会提供一个复制构造函数。因此,在函数 SomeFunc(Sample x) 中,应该创建和销毁 SomeFunc() 的局部对象,即 Sample 类型的 X,而 main() 中的 Sample 类型对象 (s1) 应该保持完整,只有在之后才能释放主要导出。请回答为什么会出现上述行为?

最佳答案

为什么会出现上述行为??

简答:
因为您没有关注 Rule of Three

长答案:
你的类(class)有一个指针成员 ptr使用构造函数中的动态内存分配和析构函数中的释放,而您的代码在传递给函数时创建对象的临时拷贝 SomeFunc()通过调用由编译器隐式生成的复制构造函数,它创建一个 shallow copy 指针成员。一旦临时对象在函数调用结束时被销毁,内存就会在析构函数中被释放,你会留下一个悬空指针。当你调用函数时,这个无效指针会被进一步取消引用 PrintVal()导致未定义的行为,以段错误的形式出现。

如何避免这个问题?

简答:
遵循三原则。

长答案:
您应该提供一个复制构造函数来创建指针成员的深层拷贝 ptr .这确保了在 member 中创建的对象的指针成员在程序的整个生命周期内保持有效。

编辑:
实际上,这个问题甚至可能在函数被调用之前就出现了,特别是当你调用:

Sample s1= 10;

这会调用转换构造函数,

 Sample(int i)

创建临时 Sample然后用于构建 s1 的对象通过调用隐式复制构造函数来对象,如果是这种情况,创建的临时对象将在创建 s1 后被销毁确实离开指针成员 ptr处于悬空状态。

但是,大多数编译器将使用 Return Value Optimization(RVO) 通过复制省略来应用优化。 从而消除了调用复制构造函数的需要,因此这可能不是问题。

无论哪种情况,问题的解决方案都是一样的。

关于c++ - 复制构造函数 : When storage is freed?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9732444/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com