Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
就地修改并返回副本有意义吗? 注:我在标注Python和C++,因为我在这两个例子中都看到过,但是问题是语言不可知。_C++_Python_Mutable - Fatal编程技术网

就地修改并返回副本有意义吗? 注:我在标注Python和C++,因为我在这两个例子中都看到过,但是问题是语言不可知。

就地修改并返回副本有意义吗? 注:我在标注Python和C++,因为我在这两个例子中都看到过,但是问题是语言不可知。,c++,python,mutable,C++,Python,Mutable,修改对象的函数或类方法有两种选择:直接修改相关对象中的数据,或创建一个新副本并返回它,同时保留原始副本不变。通常,您可以通过查看函数返回的内容来判断哪个是哪个 有时,您会发现一个函数尝试同时执行这两项操作,修改原始对象,然后返回该对象的副本或引用。是否存在这样的情况,即这比只做一个或另一个有任何优势 我见过or的例子,它依赖于返回对对象的引用,但这似乎是一种特殊情况,在上下文中应该是显而易见的 我的第一个坏例子直接来自,并说明了可变默认参数的问题。对我来说,这个例子是不现实的:如果函数修改了它的

修改对象的函数或类方法有两种选择:直接修改相关对象中的数据,或创建一个新副本并返回它,同时保留原始副本不变。通常,您可以通过查看函数返回的内容来判断哪个是哪个

有时,您会发现一个函数尝试同时执行这两项操作,修改原始对象,然后返回该对象的副本或引用。是否存在这样的情况,即这比只做一个或另一个有任何优势

我见过or的例子,它依赖于返回对对象的引用,但这似乎是一种特殊情况,在上下文中应该是显而易见的

我的第一个坏例子直接来自,并说明了可变默认参数的问题。对我来说,这个例子是不现实的:如果函数修改了它的参数,那么使用默认值就没有意义,如果它返回一个副本,那么应该在进行任何修改之前进行复制。问题的存在只是因为它试图同时做到这两个方面

def f(a, L=[]):
    L.append(a)
    return L
第二个例子来自微软C++的功能。文档中对返回值作了如下说明:

返回所有大写字符的字符串副本


这导致人们期望原始版本保持不变。部分问题在于文档有误导性,如果查看原型,您会发现它返回了对字符串的引用。除非仔细观察,否则不会注意到这一点,并且将结果分配给新字符串编译时不会出错。这个惊喜来得很晚。

C++中有一些明显的例子,在这里你想修改对象并返回引用:

  • 任务:

    T & T::operator=(T && rhs)
    {
        ptr = rhs.ptr;
        rhs.ptr = nullptr;
        return *this;
    }
    
    这个函数同时修改对象本身和参数,并返回对自身的引用。这样你就可以写
    a=b=c

  • IOStreams:

    std::ostream & operator<<(std::ostream & os, T const & t)
    {
        os << t->ptr;
        return os;
    }
    

    std::ostream&operatorC++示例Inc/Dec operator

    // Pre-Increment: Create a new object for return and modify self.
    myiterator  operator++(int) {myiterator tmp(*this); operator++(); return tmp;}
    
    
    // Post-Increment: modify self and return a reference
    myiterator&  operator++() {/* Do Stuff*/ return *this;}
    

    我不确定这个问题除了人们的意见之外还有什么答案。我的意见是强烈的不,这没有意义。您对Python的可变默认参数问题示例的评论我已经说过一段时间了;真正的问题不在于可变的默认参数,而在于该参数(可能仍在外部使用)被修改了。@Ben,这可以用一个很好的反例来回答。@delnan,函数不需要修改它的参数,除非它被显式地记录为这样做,因此默认参数永远不会被修改。如果需要修改,则无论是否使用默认值,都应复制一份。@rici您需要签出
    sorted
    @rici,不,恰恰相反-有一个函数可以原地变异,另一个函数可以返回修改后的结果。你没有一个函数同时做这两件事。这些都是很好的例子,但你可以说它们都属于“方法链接”的范畴,这个问题把它作为特例排除在外。@senderle:嗯。。。如果要放弃返回值,那么讨论返回类型是没有意义的。如果您使用的是返回值,那么这始终是一种“链接”,不是吗?@KerrekSB如果您能想出一个返回不同对象的好用例,那就不是了。请注意,
    a=b=c
    变成了
    a=(b=c)
    ,所以返回一个副本就可以了。对于链接,
    (a=b)=c
    需要参考。很好的例子,隐藏在显而易见的地方。我认为这并不适合。您要么已复制并返回(未修改),要么未复制并返回引用。@Xeo:Pre:is 1)复制。2) 修改自我(就地)。3) 返回副本。