C++ 是否返回语句复制值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1529447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:18:32  来源:igfitidea点击:

Does return statement copy values

c++return

提问by ldog

I am wondering about this because of scope issues. For example, consider the code

由于范围问题,我对此感到疑惑。例如,考虑代码

typedef struct {
    int x1;/*top*/
    int x2;/*bottom*/
    int id;
} subline_t;



subline_t subline(int x1, int x2, int id) {
    subline_t t = { x1, x2, id };
    return t;
}

int main(){
    subline_t line = subline(0,0,0); //is line garbage or isn't it? the reference
    //to subline_t t goes out of scope, so the only way this wouldn't be garbage
    //is if return copies
}

So my question is, will the return statement always copy? In this case it seems to work, so I am led to believe that return does copy. If it does copy, will it copy in every case?

所以我的问题是,return 语句会一直复制吗?在这种情况下它似乎有效,所以我相信 return 确实复制。如果它确实复制,它会在每种情况下复制吗?

采纳答案by Greg Hewgill

Yes, in that case there will be a copy made. If you change the function declaration like this:

是的,在这种情况下会制作一份副本。如果您像这样更改函数声明:

subline_t &subline(int x1, int x2, int id) {

then no copy will be made. However, in your specific case it would not be valid to return a reference to an object allocated on the stack. The problem is that the object would be destructed and invalidated before the caller had a chance to use it.

那么就不会复制。但是,在您的特定情况下,返回对堆栈上分配的对象的引用是无效的。问题是对象会在调用者有机会使用它之前被破坏和失效。

This is related to the common Return Value Optimizationfor C++ that can avoid doing an actual copy operation in the case you have described. The end result is (or should be) the same as if a copy were done, but you should be aware of the optimization. The presence of this optimization can, in some cases, change the observable behaviour of the program.

这与C++的常见返回值优化有关,它可以避免在您描述的情况下进行实际的复制操作。最终结果与(或应该)与完成副本相同,但您应该了解优化。在某些情况下,这种优化的存在会改变程序的可观察行为。

回答by Tom

In your case , it will return a copy

在您的情况下,它将返回一个副本

If your code was

如果您的代码是

subline_t& subline(int, int)

then it would return a reference, which would yield in undefined behaviour.

然后它会返回一个引用,这会导致未定义的行为。

回答by Alex Martelli

Yes, for a function declared to return a struct, returnof such a struct will copy it (though the compiler is empowered to optimize the copy away, essentially in cases where it can prove the optimization is semantically innocuous, you can reason "as if" the copying was guaranteed).

是的,对于声明返回 a 的函数structreturn这样的结构将复制它(尽管编译器有权优化副本,基本上在它可以证明优化在语义上无害的情况下,您可以推理“好像”保证复制)。

However, since you didtag this as C++, not C, why not supply your structwith a constructor, instead...? Seems clearer and more direct...!-)

但是,既然您确实将其标记为 C++,而不是 C,为什么不为您struct提供一个构造函数,而不是...?看起来更清晰、更直接……!-)

回答by Andrew Keith

yes , the return is a copy

是的,返回的是副本

subline_t subline(int x1, int x2, int id) {
        subline_t t = { x1, x2, id };
        return t;
}

If you put a referencer, then its not a copy

如果你放了一个引用,那么它不是一个副本

subline_t & subline(int x1, int x2, int id) {
        subline_t t = { x1, x2, id };
        return t; // will result in corruption because returning a reference
}

回答by csj

It will always return a copy.

它总是会返回一个副本。

If you want to avoid the performance hit of copying the object on return, you can declare a pointer, build an instance of the object using new, and return the pointer. In that case, the pointer will be copied, but the object won't be.

如果您想避免在返回时复制对象的性能影响,您可以声明一个指针,使用 new 构建对象的实例,然后返回该指针。在这种情况下,将复制指针,但不会复制对象。

回答by Artyom

Returing objects in C++ done by value and not by reference.

在 C++ 中返回对象是通过值而不是引用来完成的。

the reference to subline_t t goes out of scope

对 subline_t t 的引用超出范围

No, the object is copyed.

不,对象是复制的。

will the return statement always copy

return 语句是否总是复制

Yes and not... Semantically it behaves like copy, but there is something that is called return value optimization that saves copy constructor.

是的,不是...语义上它的行为类似于复制,但有一种叫做返回值优化的东西可以节省复制构造函数。

foo make_foo()
{
    foo f(1,2,3);
    return f;
}

foo ff=make_foo(); /// ff created as if it was created with ff(1,2,3) -- RVO
foo ff2;
ff2=make_foo(); /// instance of foo created and then copied to ff2 and then old
                /// instance destroyed

回答by Roddy

It returns a copy, which is what you want it to do. Changing it to return a reference will result in undefined behaviour in the assignment to line.

它返回一个副本,这正是您希望它执行的操作。将其更改为返回引用将导致行分配中的未定义行为。

However, the idiomatic way to do this in C++ is with constructors and assignment lists. This encapsulates code and data structures better, and allows you to avoid the plethora of intermediate objects that compilers are free to construct/destruct/copy.

然而,在 C++ 中实现这一点的惯用方法是使用构造函数和赋值列表。这更好地封装了代码和数据结构,并允许您避免编译器可以自由构造/销毁/复制的过多中间对象。

struct subline_t {
        int x1;/*top*/
        int x2;/*bottom*/
        int id;

// constructor which initialises values with assignment list.
  subline_t(int the_x1, int the_x2, int the_id) :
    x1(the_x1),
    x2(the_x2),
    id(the_id)
  {
  }
};


int main(){
    subline_t line2(0,0,0); // never requires a copy or assignment.
}

回答by Alex K.

The returned class or struct may or may not be copied, depending if the compiler uses copy elision. See the answers to What are copy elision and return value optimization? In short, whether it is copied or not depends on a number of things.

返回的类或结构可能会或可能不会被复制,这取决于编译器是否使用复制省略。请参阅什么是复制省略和返回值优化的答案简而言之,它是否被复制取决于很多事情。

You can of course avoid a copy by returning a reference. In the case of your example, returning a reference is invalid (though the compiler will allow it) because the local struct is allocated on the stack, and therefor the returned reference refers to a deallocated object. However, if the object was passed to your function (directly or as a member of an object) you can safely return a reference to it and avoid copy-on-return.

您当然可以通过返回引用来避免复制。在您的示例的情况下,返回引用是无效的(尽管编译器会允许它),因为本地结构是在堆栈上分配的,因此返回的引用是指已释放的对象。但是,如果对象被传递给您的函数(直接或作为对象的成员),您可以安全地返回对它的引用并避免返回时复制。

Finally, if you cannot trust copy elision and you want to avoid copies, you can use and return a unique_ptrinstead of a reference. The object itself will not be copied, although the unique_ptritself may or may not be (again, depending on copy elision!). Copying/moving a unique_ptris however very cheap if copy elision of the unique_ptrdoes not happen for some reason.

最后,如果您不信任复制省略并且想要避免复制,则可以使用并返回 aunique_ptr而不是引用。对象本身不会被复制,尽管它unique_ptr本身可能会或可能不会被复制(同样,取决于复制省略!)。unique_ptr但是,如果unique_ptr由于某种原因没有发生 的复制省略,则复制/移动 a非常便宜。

Here is an example using unique_ptr:

这是一个使用示例unique_ptr

#include <memory>

struct A {
public:
  int x;
  int y;

  A(int x, int y) : x(x), y(y) {
  }
};

std::unique_ptr<A> returnsA() {
  return std::make_unique<A>(3, 4);
}

int main() {
  auto a = returnsA();
}

Note that you must (unfortunately) declare a constructor for your struct, or else make_uniquewill not compile due to inadequacies of C++.

请注意,您必须(不幸的是)为您的结构声明一个构造函数,否则make_unique将由于 C++ 的不足而无法编译。

回答by Jacob

For the structure subline_tyou've defined, yes, it will always return a copy.

对于subline_t您定义的结构,是的,它总是会返回一个副本。

回答by Alphaneo

Just FYI, since in this case you are using only a struct(ure), it is the same behavior as in C language.

仅供参考,因为在这种情况下您只使用结构(ure),它与 C 语言中的行为相同。

Though this is a language feature, it is recommended that it shall not be used

虽然这是语言特性,但建议不要使用