std ::将成员函数绑定到nullptr的实例,导致看似随机的这个指针

时间:2013-10-06 15:08:40

标签: c++ c++11 undefined-behavior

我在gcc-4.8(通过Coliru)和Visual Studio 2013 RC上测试了以下程序:

#include <iostream>
#include <functional>

using namespace std;

struct foo {
    void bar() {
        cout << "this = " << this << endl;
    }
};

int main() {
    try {
        foo *ptr = nullptr;
        function<void ()> fun = bind(&foo::bar, *ptr);
        fun();
    } catch (const bad_function_call &e) {
        // never reached
        cout << "bad_function_call thrown: " << e.what() << endl;
    } 

    cin.get();
}

我理解我通过解除引用nullptr在这里引起了未定义的行为,但是我不理解我的代码的输出。在我的理解中,这应该导致bad_function_call(因为这是从我猜到的时候调用这个std :: function时应该抛出的东西)或者至少打印“this = 0”。

没有。输出是“this =”后跟一些指针,在我测试的两个编译器上都不是nullptr。但是,访问它会导致分段错误。

标准中是否有一个条款指定了这个?或者它只是实现定义的“未定义行为”?

编辑:作为补充:以下代码在我的机器上输出“this = 0”:

foo *ptr = nullptr;
ptr->bar();

2 个答案:

答案 0 :(得分:1)

bind存储参数的副本会发生什么。参数类型为foo(因为您传递*ptr),因此会生成副本。当然,副本作为源获得了无效的参数,但是没有使用它,因此这似乎有效。因此,foo的新实例存储在绑定对象中,这是您看到的地址。

当您说您看到分段错误时,您会参考您的真实代码,而不是您在此处提供的示例,对吧?在您的真实代码中,我想copy-ctor似乎可以工作,但是当您访问其(可能是无效的)成员时,会创建一个导致分段错误的实例。

答案 1 :(得分:0)

“未定义”表示未定义。当你有未定义的行为时会发生什么事情的推理是徒劳的,除非你的编译器记录它的作用。