c++将结构体的所有权转移给函数

C++ transfer ownership of a struct to a function

本文关键字:转移 函数 所有权 结构体 c++      更新时间:2023-10-16

是否有可能将c++(或c++ 0x)中的局部变量的所有权转移到函数中,在返回后使其未定义,从而可以进行优化?

struct A {
    int a[100000];
};
int func(A& s){
    //s should now be "owned" by func and be undefined in the calling function
    s.a[2] += 4;
    return s.a[2];
}
int main(){
    A s;
    printf("%dn", func(s));
    //s is now undefined
}

我希望函数"func"被优化为简单地返回s.a[2]+4,但不改变内存中的实际值,就像如果"s"是"func"中的局部变量一样。如果它不能在标准c++中完成,那么在c++中的一些扩展是否可能?

不,这是不可能的,无论是标准还是通过扩展,这是因为没有优化值。编译器可以简单地证明在这种情况下不再有对局部变量的引用。如果没有其他方法,您可以通过执行

简单地模拟效果
int main() {
    {
        A s;
        printf("%dn", func(s));
    }
}

这样做是非常危险的,没有任何好处。

把优化留给编译器——在简单的情况下,它可能会做。

不要忘记——过早优化是万恶之源。

我希望一个合理的优化编译器能够在没有任何特殊提示的情况下进行这样的优化,如果局部变量s在函数返回后真的没有被引用,假设变量和函数在相同的编译单元中,或者您启用了某种形式的链接时代码生成。

你可以通过限定局部变量的作用域来帮助优化器,使它在函数调用后的一个引用之外不能被访问:

int main() {
    {
        A s;
        printf("%dn", func(s));
    } //s is now undefined
}

如果你有一个特定的情况,似乎没有像你认为的那样有效地优化,那么也许你可以提供更多关于你的情况的细节。在这种情况下,我有点不清楚你所说的函数"拥有"局部变量到底是什么意思,因为你实际上想在函数返回后访问它。

您正在混合不同的问题,如所有权,堆栈展开和值参数。

是否可以转移局部变量的所有权

。局部变量是定义作用域的局部变量,其他人不能以任何方式看到或操作它们。可以将局部变量的值、对局部变量的引用或局部变量的地址传递给函数。当传递局部变量的引用或指针时,调用者可以操作变量的内容,但绝不能影响调用者框架中变量的作用域。最常见的"所有权"转移意味着按值转移指针,并依赖于被调用者获得分配的内存的所有权。所有形式的变量传递(通过值,通过ref,通过指针)都可以处理这个问题,内存分配所有权的问题是不同的。

我希望函数"func"被优化为简单地返回s.a[2]+4,但不改变内存中的实际值,

那就照做,为什么要把事情弄得更复杂呢?

int func(const A& s){
    return s.a[2] + 4;
}

这将做你所描述的,但非常不可能这是你真正要求的。大胆地说,调用一些特异功能有人会猜测你真正想问的是一个对象可以在被调用方作用域中被改变同时在调用方作用域中保持完整吗?答案显然是否定的,因为内存不能根据调用者的不同而具有不同的值。您可以传递对象的副本(按值传递),这将允许调用方按照其认为合适的方式操作自己的对象副本,而不会影响调用方作用域的原始对象。或者你可以传递const引用,防止被调用方修改它,并让被调用方复制出它需要修改的任何内容。

我很惊讶没有其他人发表过这个,但听起来最接近你想要的是简单地删除引用,并将函数调用放在单独的作用域

int func(A s){ //removed the &
    //s is "owned" by func and changes don't touch anyone else's A objects
    s.a[2] += 4;
    return s.a[2];
}
int main(){
    {
        A s;
        printf("%dn", func(s));
        // s hasn't changed, func had it's own copy.
    } // s goes out of scope and is deleted
    //s is now undefined
}

如果你喜欢的话,你也可以让它基于指针。下面的代码示例改变了你的func(A),让它接受一个指针的引用,这样它就可以在释放后安全地变为null。

这有点不太好,但如果你绝对需要的话,这是可能的。然而,这可能是一个可以避免的过早优化。

int func(A*& s) {
    int retVal = s->a[2] + 4;
    delete s;
    s = NULL;
    return retVal;
}
int main() {
   A* s = new A();
   printf("%dn", func(s));
}

您可以使用旧的c++ 03 auto_ptr来完成此操作。调用函数留下一个auto_ptr,该auto_ptr指向nullptr,而函数接管并删除s。

int func(std::auto_ptr<A> s){
    //s is "owned" by func and be undefined in the calling function
    s.a[2] += 4;
    return s.a[2];
}
int main(){
    std::auto_ptr<A> s = new A();
    printf("%dn", func(s)); //destructive copy of pointer
    //s is now nullptr
}