3

次のコードは例外をスローします

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_function_call> >'
  what():  call to empty boost::function

行でf()(ブロックの実行中):

void foo(); // assume this is defined somewhere
boost::function<void()> f = boost::bind(&foo);

^(void) {
   f();
}();

ただし、ブロックに関するドキュメントによると、

一般に、ブロック内でC++オブジェクトを使用できます。メンバー関数内では、メンバー変数および関数への参照は、暗黙的にインポートされたこのポインターを介して行われるため、変更可能に見えます。ブロックがコピーされる場合に適用される2つの考慮事項があります。

  • スタックベースのC++オブジェクトの__blockストレージクラスがある場合は、通常のコピーコンストラクターが使用されます。

  • ブロック内から他のC++スタックベースのオブジェクトを使用する場合は、constcopyコンストラクターが必要です。次に、そのコンストラクターを使用してC++オブジェクトがコピーされます。

これは通常は正しいようです。f上記を、を含む単純なクラスのインスタンスに置き換えるとoperator()()、上記のコードは期待どおりに実行されます。

なぜバージョンが機能しないのboost::functionですか?

4

2 に答える 2

1

で宣言を変更すると__block、正しく動作するようです。

__block boost::function<void()> f = boost::bind(&foo);

これがなぜなのかはまだわかりません-@Richardが上記のコメントで言及しているように、「通常のコピーコンストラクター」ではなく「constコピーコンストラクター」に関係している必要があります。ただし、この違いを確認する方法はわかりません。以下はうまくいきます:

const boost::function<void()> f = boost::bind(&foo);
const boost::function<void()> g(f);
g();

それが「const copy constructor」を呼び出さない場合、何が起こるかわかりません。

于 2011-04-06T05:05:00.117 に答える
0

あなたの答えの例、

const boost::function<void()> f = boost::bind(&foo);
const boost::function<void()> g(f);
g();

operator()呼び出し先が作成されたのと同じスコープで呼び出しているため、機能します。f()ブロック スコープ外でも機能し、呼び出しfoo()はブロック スコープ内で機能します。これは、従来の関数であり、呼び出されたときに「変更された」とは見なされないためです。const コピー コンストラクターへの参照呼び出しは、オブジェクトを包含スコープからブロック スコープに渡すときに行われます。const コピー コンストラクターに存在する違いが何であれ、オブジェクトの一部をブロック スコープにコピーできていないように見えます。

于 2011-04-09T13:41:37.023 に答える