2013-10-06 24 views
1

我测试下面的程序上的gcc-4.8(经由Coliru)和Visual Studio中2013 RC:的std ::在nullptr一个成员函数绑定到一个实例引起看似随机的该指针

#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(); 
} 

我理解我通过dereferencing nullptr导致未定义的行为,但我不明白我的代码的输出。根据我的理解,这应该导致bad_function_call(因为这是调用std :: function时应该抛出的东西,根据我的猜测)或者至少打印“this = 0”。

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

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

编辑:正如加法:下面的代码输出“这一= 0”我的机器上:

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

回答

1

什么情况是,bind存储参数的副本。参数的类型为foo(因为您传递的是*ptr),因此会进行复制。当然,该副本获得一个无效的参数作为源,但没有使用,因此这似乎工作。因此,foo的新实例存储在绑定对象内,这是您看到的地址。

当你说你看到一个分段错误时,你引用你的真实代码,而不是你在这里给出的例子,对吧?在你真实的代码中,我猜copy-ctor似乎有效,但是当你访问它的(可能是无效的)成员时,会创建一个导致分段错误的实例。

+0

所以传递ref(* foo)应该导致“this = 0”成为输出呢?去做一些测试。编辑:它。 –

+0

@DominikLohmann它的确如此。 :) –

+0

分段错误是关于在foo :: bar中访问它。我想知道为什么它不会抛出std :: bad_function_call,因为这将有意义恕我直言。 –

0

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

+1

虽然我在标准方面同意你的看法,但在特定实现方面,理解为什么某些方法可行(即使是离奇的)也是有趣的。 –

+0

@MatthieuM。 - “有趣”并不否定“徒劳”。 '' –

+0

*所有知识值得拥有* - Anafiel Delaunay –

相关问题