0

関数が戻った後に関数への入力引数を無効として宣言する方法は C++11 にありますか?

簡単な例として、左下隅の座標と右上隅の座標を持つ四角形オブジェクトがあるとします。この四角形オブジェクトを関数への非 const 参照で渡すと、関数は自由に四角形メモリに副作用を与えます。その関数がスケーリングする必要があり、新しいメモリにコピーするのではなく、その場で動作したい場合、関数が戻った後、渡された四角形の内容が有効でなくなったことを C++11 でどのように宣言できますか?呼び出された関数によって変更された可能性がありますか?

四角形クラスを変更したくはありませんが、関数呼び出しの宣言に、関数からの戻り時に参照によって渡されたメモリが無効であると見なされ、呼び出し元が関数呼び出しが戻った後にそれを使用しようとします。C++11でこれを行う方法はありますか?

4

4 に答える 4

3

途中まで行くことができます:

void function(rectangle&& x) // r-value reference
{
    // ...
}

rectangle r;

function(r); // error
function(std::move(r)); // okay, explicitly made into an rvalue

// now (by convention) r shouldn't be used, because it's been moved

とはいえ、C++ の型システムは、再度使用するとエラーが発生するほど強力ではありません。

しかし、あなたのデザインには疑問があります。コピペして何が悪いの?または、引数が変更されることを関数名で明確にしないのはなぜですか? (のようにstd::swap。)

于 2011-12-14T12:41:54.183 に答える
1

関数への参照としてBoost.Optionalを渡し、最後に関数に変数をリセットさせます。

void MyFunction(boost::optional<Rectangle> &rectangle)
{
    // Do something with rectangle here
    rectangle.reset();
}

boost::optional<Rectangle> rectangle(Rectangle(0, 0, 0, 0));
// You can also set the optional rectangle to another value
rectangle = Rectangle(100, 100, 200, 200);
MyFunction(rectangle);
// Now rectangle won't be initialised and shouldn't be used
ASSERT(!rectangle.is_initialized());

そうは言っても、これは設計上の問題のように聞こえます。これが不要になるように関数を再構築できますか?

于 2011-12-14T13:19:01.293 に答える
0

関数呼び出しの宣言に、参照によって渡されたメモリが関数から戻ったときに無効と見なされ、呼び出し元がその後に使用しようとするとエラーが発生することを示す方法があります。関数呼び出しが返されます。

ここでいくつか混乱していると思います。

1つは、メモリのブロブを関数に渡すのではなく、オブジェクト(タイプrectangle)に渡すことです。オブジェクトは単なるメモリの塊ではありません。
オブジェクトはコンストラクターを実行し、メモリのブロブをオブジェクトに変換し、オブジェクトをある決定的な状態にセットアップしました。オブジェクトが死ぬと、そのデストラクタが実行され、オブジェクトが再びメモリのブロブに変わります。これら2つの間に、それはオブジェクトです。
オブジェクトを無効にするには、オブジェクトの状態の一部である1つ以上のフラグを設定し、無効化を通知するか(IOストリームがそれを行います)、またはそのデストラクタを呼び出す必要があります。これは(通常)間接的にのみ行う必要があります。にdeletenewを使用して、または暗黙的にスコープから外れるようにして作成されたingおよびオブジェクト(自動オブジェクトの場合)。

これにより、渡されたオブジェクトを変更する関数が残ります。
関数は、そのシグネチャによって引数を変更する可能性を示します。オブジェクトが関数にどのように渡されるかを見ると、関数が引数を変更する可能性があるかどうかがわかります。関数を呼び出す必要があり、何らかの理由で変更されてはならないオブジェクトを、関数が変更される可能性があることを示す引数として渡す必要がある場合は、そのオブジェクトのコピーを渡す必要があります。実物。

ここで触れていない何らかの理由でオブジェクトが関数の引数として使用された後にオブジェクトが使用されないようにしたい場合は、オブジェクトを小さな囲みスコープに入れるだけです。

void f()
{
  g();
  {
    rectangle rect(...);
    h(r);
  } // rect dies here
  // rect not accessible here
  g();
}
于 2011-12-14T14:45:24.710 に答える
0

この例では、長方形をスケーリングするとどのように無効になるのでしょうか? オブジェクトをその場で変更する場合、有効なままにする必要があります。そうしないと、操作は役に立ちません。

呼び出し元として、const 以外の参照によってオブジェクトを関数に渡すときは、常に副作用を予期する必要があります。

オブジェクトが本当に無効になる唯一の理由は、そこから移動した場合です。その場合、呼び出し元は を使用して明示的に渡す必要がstd::moveあるため、後でオブジェクトが有効ではないことがわかります。

于 2011-12-14T12:41:04.853 に答える