为什么这段代码只打印42?

时间:2009-07-18 19:11:05

标签: c++ gcc auto-ptr

有人可以向我解释为什么这段代码只打印“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我在解决方案中使用不同的值尝试了此代码,并且我总是得到“正确”的值,因此它似乎不是随机的幸运值。

7 个答案:

答案 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)

您没有遇到崩溃,因为“解决方案”方法不需要实际使用类成员。如果你要归还某个成员或某物,你可能会崩溃。