我有一个名为intWrapper
的int的包装类,以及一个添加两个数字的函数addN
,定义如下:
intWrapper* addN(intWrapper *first, intWrapper *second)
{
intWrapper c;
c.setData(first->getData() + second->getData());
return &c;
}
然后,在 main()函数中,我这样做:
intWrapper first(20), second(40);
intWrapper* t = addN(&first, &second);
cout << (*t).getData() << endl;
在Dev-c ++(MingW32)中,它按预期执行,并将打印值60
,但在Visual C ++中,我得到值-858993460
。
但是,如果我使用new关键字在addN函数中创建一个新对象,它也会在Visual C ++中输出60
。我很感兴趣为什么会这样。有什么想法吗?
完整代码在这里:
#include <iostream>
using namespace std;
template<typename T, T defaultValue>
class Wrapper
{
private: T n_;
public:
Wrapper(T n = defaultValue) : n_(n) {}
T getData()
{
return n_;
}
void setData(T n)
{
n_ = n;
}
};
typedef Wrapper<int, 47> intWrapper;
intWrapper* addN(intWrapper *first, intWrapper *second)
{
intWrapper c;
c.setData(first->getData() + second->getData());
return &c;
}
int main()
{
intWrapper p;
cout << p.getData() << endl;
intWrapper first(20), second(40);
intWrapper* t = addN(&first, &second);
cout << (*t).getData() << endl;
system("PAUSE");
return 1;
}
答案 0 :(得分:7)
这是未定义的行为:您正在返回一个指向局部变量的指针,该函数在函数返回时将被销毁,这意味着返回值是悬空指针。
未定义的行为意味着任何事情都可能发生:它可能会崩溃,它可能看起来“正常”工作或可能无法正常工作。
当您使用new
时,intWrapper
实例将存在于函数范围之外,并且不是未定义的行为,并且将正常工作(对于VC和MingW32)。当不再需要时,请记得delete
返回的intWrapper*
。
答案 1 :(得分:0)
在Dev-c ++(MingW32)中,这按预期执行
它没有按预期执行。 该程序使用未定义的行为。当你这样做时,任何事情都会发生。
返回指向局部变量的指针。从函数返回时,局部变量不再存在。这意味着该变量以前使用的内存可能包含任何,甚至可能不再可读(即您将获得段错误/访问冲突)。除非你喜欢玩俄罗斯轮盘赌,并希望在你的程序中完全不可预测的行为,否则你不应该这样做。
按值返回IntWrapper(您需要复制构造函数和赋值运算符):
intWrapper addN(intWrapper *first, intWrapper *second)
{
intWrapper c;
c.setData(first->getData() + second->getData());
return c;
}
,或者用new
分配,然后返回结果(以后忘记删除)
intWrapper* addN(intWrapper *first, intWrapper *second)
{
intWrapper *c = new intWrapper;
c->setData(first->getData() + second->getData());
return c;
}
或使用智能指针(shared_ptr)自动删除它。