如何在C ++ 11中调用函数后将对象声明为无效?

时间:2011-12-14 12:35:28

标签: c++ const c++11 side-effects

在C ++ 11中是否有一个函数的输入参数在函数返回后被声明为无效?

举一个简单的例子,考虑我有一个矩形对象,左下角的坐标和右上角的坐标。如果我通过非const引用将此矩形对象传递给函数,则该函数可以自由地将矩形内存副作用于其认为合适的位置。如果该函数需要扩展它而不是复制到新内存只是想要就位,那么我们怎么能在C ++ 11中声明函数返回后传入的矩形的内容不再有效,因为它们不再有效可能已被名为?

的函数修改过

我不想修改矩形类,而是在函数调用的声明中有一些方法来指示通过引用传入的内存在从函数返回时应被视为无效并且让编译器给出错误如果调用者在函数调用返回后尝试使用它。有没有办法在C ++ 11中做到这一点?

4 个答案:

答案 0 :(得分: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。)

答案 1 :(得分: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());

说了这么多,这听起来有点像设计问题。你能重新构建你的功能,所以这不是必要的吗?

答案 2 :(得分:0)

在我们的示例中,如何缩放矩形使其无效?如果你就地改变对象,它应该保持有效,否则你的操作没用。

作为调用者,当通过非const引用将对象传递给函数时,您应该始终期待副作用。

对象变为真正无效的唯一原因是你从它移动。在这种情况下,调用者必须使用std::move显式传递它,因此他们知道该对象之后无效。

答案 3 :(得分:0)

  

我希望在函数调用的声明中有一些方法来指示通过引用传入的内存在从函数返回时应被视为无效并且如果调用者尝试使用,则编译器会给出错误它在函数调用返回之后。

我认为你在这里混淆了一些事情。

首先,您不会将 一块内存 传递给一个函数,而是一个 对象 (类型rectangle)。 一个对象不仅仅是一块内存。
对象已运行 构造函数 将一块内存转换为对象 ,并将对象设置为一些确定的状态。当对象死亡时, 析构函数 将运行, 再次将对象转换为内存块 。在这两者之间,它是一个对象 要使对象无效,您需要设置一个或多个标志,这些标志是对象状态的一部分并且信号失效(IO流会这样做),或者您需要调用它的析构函数 - 这通常是您应该间接执行的,或者通过delete和使用new创建的对象,或通过让它超出其范围(对于自动对象)隐式地使用。

将功能留给传递给他们的 更改 对象 函数 表示 可能会通过 签名 更改参数,并查看{{3}你看看这个函数是否会改变它。如果需要调用一个函数,并且需要传递一个对象,由于某种原因,该对象必须不被更改为函数指示它可能会更改的参数,您需要传递 副本< / em> 该对象,而不是真实的东西。

如果你想要防止一个对象被用作函数参数后出于某种原因我没有碰过这里,你可以简单地把它放在一个小的封闭范围内:

void f()
{
  g();
  {
    rectangle rect(...);
    h(r);
  } // rect dies here
  // rect not accessible here
  g();
}