如何将函数标记为使其参数无效

时间:2015-03-15 18:26:07

标签: c++ c++11 types move-semantics rvalue-reference

我有一个接受指针向量的函数f。函数f完成后,这些指针不再有效。注意,没有必要更改向量本身,我只是想鼓励调用者在调用f之后不使用指针。 f有三种可能的签名:

移动签名

void f(vector<void*> &&v); // because the pointers in v are no longer valid. 
// This signature also allows me to have f call clear() on v.

const签名

void f(const vector<void*> &v); // because the pointers in v are no longer valid,
// but we don't have to change the vector v.

指针签名

void f(vector<void*> *v); // The functino modifies v in a predictable way 
// (it clears it). A pointer is used instead of a reference so that
// calls to the function will have a '&' which clearly shows to the reader
// that this function modifies its argument. '*' is different from '&&' since '&&' 
// may imply "do not use v, but it is unknown how it will be modified" while 
// '*' implies a clear semantic for how v is changed.

在C ++ 11中使用哪个签名更具惯用性?

6 个答案:

答案 0 :(得分:2)

怎么样

void f(vector<void*> v);

使用它:

vector<void*> myVec = /*...*/;
f(std::move(myVec));

如果f逻辑上需要向量的所有权,这是惯用的方式。它允许调用者决定是将向量移动还是复制到f

如果调用者实际上希望f修改他的向量(因此向量实际上是一个输入/输出参数),那么这并不适合你的需要。然而,输入/输出参数很糟糕。函数应该将输入作为参数并将输出作为返回值返回。这就是上帝的意图。

答案 1 :(得分:2)

如果您真的想使用类型系统执行此操作,则始终可以使用您自己的类型对额外信息进行编码。

template<class T>
struct invalidates_contained_pointers;

template<class T>
invalidates_contained_pointers<T>* contents_will_be_invalidated(T* ptr) {
    return reinterpret_cast<invalidates_contained_pointers<T>*>(ptr);
}

void f(invalidates_contained_pointers<vector<void*>> *v){
    auto pv = reinterpret_cast<vector<void*> *>(v);
    // ...
}

f(contents_will_be_invalidated(&vec));

类似的方法可用于参考。

答案 2 :(得分:1)

简短的回答:没有办法做到这一点。唯一的官方&#39;是相反的:一个签名,它承诺函数f(..)不会改变它的参数:const关键字。

通常一个人坚持以下内容:

  • 不修改其参数的函数要么将其参数作为值复制获取,要么使用const明确标记其参数

  • 由非const引用传递的参数,移动或指向非const对象的参数应该被读作&#34;这个参数很可能被被调用函数f(...)修改&#34;

答案 3 :(得分:1)

正如其他人所说的那样,类型系统不允许您在此函数调用之后指出类似“不要使用此数据”的内容。你可以做什么:

void f(vector<void*> &v)
{
  // ... use v ...
  v.clear(); // encourage callers not to use the pointers after the call
}

答案 4 :(得分:1)

f应该清除向量,如果它正在删除指针(或释放它们处理的任何内容)。让调用者留下一个intederminate值向量是毫无意义的。

所以f应该通过非const引用接受向量。是否要进行此左值引用或右值引用取决于您;但是左值版似乎更简单。

答案 5 :(得分:0)

在这三个中:vector<void*> *需要左值来获取地址。 const vector<void*> &允许传入左值或右值。vector<void*> &&只允许传入rvalues。

根据您的问题,使用左值或右值调用函数是有意义的,因此const vector<void*> &是显而易见的选择。

无法通过类型系统指示调用者应该停止使用包含的指针,并且您不应该尝试通过类型系统指示。通过文档说明。

相关问题