有人可以向我解释为什么这段代码只打印“42”而不是“创建\ n42”?
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class MyClass
{
public:
MyClass() {cout<<"created"<<endl;};
int solution() {return 42;}
virtual ~MyClass() {};
};
int main(int argc, char *argv[])
{
auto_ptr<MyClass> ptr;
cout<<ptr->solution()<<endl;
return 0;
}
BTW我在解决方案中使用不同的值尝试了此代码,并且我总是得到“正确”的值,因此它似乎不是随机的幸运值。
答案 0 :(得分:27)
因为它表现出未定义的行为 - 您取消引用空指针。
当你说:
auto_ptr<MyClass> ptr;
你创建一个不指向任何东西的autopointer。这相当于说:
MyClass * ptr = NULL;
然后当你说:
cout<<ptr->solution()<<endl;
你取消引用这个空指针。这样做在C ++中是未定义的 - 对于您的实现,它似乎有效。
答案 1 :(得分:21)
std::auto_ptr不会自动为您创建对象。也就是说,main中的ptr
初始化为null。取消引用这是不明确的行为,你恰好幸运,结果是42。
如果您实际创建了该对象:
int main(int argc, char *argv[])
{
auto_ptr<MyClass> ptr(new MyClass);
cout << ptr->solution() << endl;
return 0;
}
您将获得预期的输出。
答案 2 :(得分:3)
首先,请记住,->
的{{1}}运算符基本上转发到包含的指针。因此,对于此讨论,auto_ptr
中的代码将等同于:
main
然后请注意,编译器倾向于以非常成功的方式实现成员函数,就像将MyClass* ptr = NULL;
cout << ptr->solution() << endl;
指针作为另一个函数参数传递一样。因此,从您当前编译器的角度来看,this
中的代码就像是:
main
解决方案写为:
MyClass* ptr = NULL;
cout << solution(ptr) << endl;
在这种情况下,很明显为什么没有崩溃。
然而,正如其他人已经提到的那样,这些是编译器如何实现C ++的内部细节,这些内容未由语言标准指定。所以从理论上讲,这个代码可以像这里描述的那样在一个编译器上工作,但是崩溃或者完全在另一个编译器上做其他事情。
但实际上,即使标准不能保证这种行为,任何特定的编译器都可以保证它是否需要。例如:由于MFC依赖于此行为,因此Visual Studio不太可能停止支持它。当然,您必须研究每个特定的编译器,您的代码可能会用于确保它们确实能够保证这种行为。
答案 3 :(得分:2)
因为您不知道答案xD的问题
好像你没有调用构造函数,对吧?
答案 4 :(得分:2)
您没有创建对象的实例 你只是在创建一个智能指针。
当您调用该方法时,您将取消引用NULL指针,因此Neil提到您现在处于未定义的行为。但是,由于您的代码不会尝试访问任何成员变量,所以幸运的是它不会崩溃。
试试这个:
auto_ptr<MyClass> ptr(new MyClass);
答案 5 :(得分:1)
因为ptr
未初始化而您很幸运。您应该首先致电new
:
auto_ptr<MyClass> ptr( new MyClass );
答案 6 :(得分:1)
您没有遇到崩溃,因为“解决方案”方法不需要实际使用类成员。如果你要归还某个成员或某物,你可能会崩溃。