如何在 C++11 中函数调用后将对象声明为无效?
C++11 中是否有在函数返回后将函数的输入参数声明为无效的?
举一个简单的例子,假设我有一个矩形对象,其左下角坐标和右上角坐标。如果我通过对函数的非常量引用传递此矩形对象,则该函数可以自由地对矩形内存产生副作用,因为它认为合适。如果该函数需要对其进行缩放,而不是复制到新内存,只是想就地工作,我们如何在 C++11 中声明函数返回后,传入的矩形内容不再有效,因为它们可能已被调用的函数修改?
我不想修改矩形类,而是在函数调用的声明中采用某种方式来指示通过引用传入的内存在从函数返回时应被视为无效,并且如果调用者则让编译器给出错误尝试在函数调用返回后使用它。在 C++11 中有什么方法可以做到这一点吗?
Is there anyway in C++11 to have an input argument to a function be declared as invalid after the function returns?
For a simple example, consider that I have a rectangle object with a coordinate for the lower left corner and a coordinate for the upper right corner. If I pass this rectangle object by non-const reference to the function, the function is free to side-effect the rectangle memory in place as it sees fit. What if that function needs to scale it and rather than copying to new memory just wants to work in place, how could we in C++11 declare that after the function returns, the contents of the rectangle passed in are no longer valid as they may have been modified by the function called?
I would not want to modify the rectangle class, but instead have some way in the declaration of the function call to indicate that the memory passed in by reference should be considered invalid upon return from the function and have the compiler give an error if the caller tries to use it subsequent to the function call returning. Is there some way to do this in C++11?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你可以做到一半:
也就是说,C++ 的类型系统不够强大,如果你再次使用它,不会给你一个错误。
不过我质疑你的设计。复印有什么问题吗?或者为什么不在函数名中明确指出要修改的参数? (如
std::swap
。)You can get half-way there:
That said, the type-system is C++ is not strong enough to give you an error if you use it again.
I question your design, though. What's wrong with making a copy? Or why not make it clear in the function name that the argument is going to modified? (Like
std::swap
.)传递 Boost.Optional 作为对函数的引用,并让函数在结尾。
话虽如此,这听起来有点像一个设计问题。您可以重新构建您的功能,这样就没有必要了吗?
Pass a Boost.Optional as a reference to your function and have the function reset the variable at the end.
Having said all that, this sounds a bit like a design issue. Can you re-architecture your functions so this isn't necessary?
在我们的示例中,缩放矩形如何使其无效?如果就地改变对象,它应该保持有效,否则你的操作没有用。
作为调用者,当通过非常量引用将对象传递给函数时,您应该始终预料到副作用。
一个对象真正变得无效的唯一原因是你离开它。在这种情况下,调用者必须使用 std::move 显式传递它,以便他们知道该对象随后无效。
In our example, how would scaling the rectangle make it invalid? If you mutate the object in-place, it should remain valid, otherwise you operation is not useful.
As a caller, when passing an object to a function by non-const reference you should always expect side-effects.
The only reason where an object would become truly invalid is if you move from it. In that case the caller has to explicitly pass it using
std::move
, so they know that the object is not valid afterwards.我认为你在这里混淆了一些事情。
首先,您不会将一团内存传递给函数,而是传递一个对象(类型为
矩形
)。 对象不仅仅是一团内存。一个对象已运行其构造函数,将一块内存转换为一个对象,并将该对象设置为某种确定的状态。当对象死亡时,其析构函数将运行并再次将对象转变为内存块。在这两者之间,它是一个对象。
要使对象无效,您需要设置一个或多个标志,这些标志是对象状态和信号无效的一部分(IO 流执行此操作),或者您需要调用其析构函数 - (通常)您应该只间接执行此操作通过
delete
ing和使用new
创建的对象,或者隐式地让它超出其范围(对于自动对象)。这使得函数可以更改传递给它们的对象。
函数表明它可能通过其签名更改参数的可能性,并查看如何将对象传递给函数,您可以看到该函数是否可能会更改它。如果您需要调用函数并且需要传递一个对象,由于某种原因,该对象不能作为参数进行更改,而该函数表明它可能会更改,则需要传递一个copy< /em>那个物体,而不是真实的东西。
如果你想阻止一个对象在由于某种原因被用作函数参数后被使用,我在这里没有触及,你可以简单地将它放入一个小的封闭范围中:
I think you are confusing a few things here.
For one, you do not pass a blob of memory to a function, but an object (of the type
rectangle
). An object is more than a blob of memory.An object has had its constructor run, turn a blob of memory into an object, and setup the object to some definitive state. When the object dies, its destructor will run and turn the object into a blob of memory again. In between those two, it's an object.
To render an object invalid you need to either set one or more flags that are part of the object's state and signal invalidation (IO streams do that), or you need to call its destructor — which (usually) you should only do indirectly, either by
delete
ing and object created usingnew
, or implicitly by letting it fall out of its scope (for automatic objects).That leaves functions to change objects passed to them.
A function indicates the possibility that it might change an argument by its signature, and looking at how an object is passed to a function you see whether the function might change it. If you need to call a function and you need to pass an object that must, for some reason, not be changed as an argument for which the function indicates that it might change, you need to pass a copy of that object, rather than the real thing.
If you want to prevent an object from being used after it was used as a function argument for some reason I haven't touched here, you can simply put it into an small enclosing scope: