문 복사 값을 반환합니까?
범위 문제 때문에 이것에 대해 궁금합니다. 예를 들어, 코드를 고려하십시오.
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
}
그래서 제 질문은 return 문이 항상 복사됩니까? 이 경우 작동하는 것처럼 보이므로 반환이 복사를한다고 믿게됩니다. 복사하면 모든 경우에 복사됩니까?
예,이 경우 사본이 만들어집니다. 다음과 같이 함수 선언을 변경하면 :
subline_t &subline(int x1, int x2, int id) {
그러면 복사본이 만들어지지 않습니다. 그러나 특정 경우 스택에 할당 된 개체에 대한 참조를 반환하는 것은 유효하지 않습니다. 문제는 호출자가 사용하기 전에 객체가 파괴되고 무효화된다는 것입니다.
이는 설명한 경우 실제 복사 작업을 피할 수 있는 일반적인 C ++ 용 반환 값 최적화 와 관련이 있습니다. 최종 결과는 복사가 완료된 것과 동일하거나 동일해야하지만 최적화에 대해 알고 있어야합니다. 이 최적화의 존재는 경우에 따라 프로그램의 관찰 가능한 동작을 변경할 수 있습니다.
귀하의 경우에는 사본을 반환합니다.
코드가
subline_t& subline(int, int)
그런 다음 참조를 반환하고 정의되지 않은 동작을 생성합니다.
함수가를 반환하는 선언에 대한 예 struct
, return
이러한 구조체가 복사됩니다의 컴파일러는 권한을 부여하고 있지만 (당신이 이유 수, 그것은 최적화 의미 무해 입증 할 수있는 곳은 경우에 기본적으로, 멀리 복사 최적화 "만약 그대로" 복사가 보장됨).
그러나 이후 한 이 C로 태그 ++, C, 왜 당신을 제공하지하지 struct
않고, 생성자와 함께 ...? 더 명확하고 직접적으로 보입니다 ...!-)
항상 복사본을 반환합니다.
반환시 개체를 복사하는 성능 저하를 피하려면 포인터를 선언하고 new를 사용하여 개체의 인스턴스를 빌드 한 다음 포인터를 반환 할 수 있습니다. 이 경우 포인터는 복사되지만 개체는 복사되지 않습니다.
예, 반품은 사본입니다.
subline_t subline(int x1, int x2, int id) {
subline_t t = { x1, x2, id };
return t;
}
참조자를 넣으면 사본이 아닙니다.
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
}
참조가 아닌 값에 의해 수행되는 C ++에서 개체를 복원합니다.
subline_t t에 대한 참조가 범위를 벗어납니다.
아니요, 개체가 복사됩니다.
return 문이 항상 복사됩니까?
예, 아닙니다 ... 의미 상 복사처럼 동작하지만 복사 생성자를 저장하는 반환 값 최적화라는 것이 있습니다.
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
원하는 작업 인 복사본을 반환합니다. 참조를 반환하도록 변경하면 줄 할당에서 정의되지 않은 동작이 발생합니다.
그러나 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.
}
subline_t
정의한 구조의 경우 예, 항상 복사본을 반환합니다.
반환 된 클래스 또는 구조체는 컴파일러가 복사 제거를 사용하는지 여부에 따라 복사되거나 복사되지 않을 수 있습니다. 복사 제거 및 반환 값 최적화 란 무엇입니까?에 대한 답변을 참조하십시오 . 요컨대, 복사 여부는 여러 가지에 달려 있습니다.
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_ptr
instead of a reference. The object itself will not be copied, although the unique_ptr
itself may or may not be (again, depending on copy elision!). Copying/moving a unique_ptr
is however very cheap if copy elision of the unique_ptr
does not happen for some reason.
Here is an example using 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_unique
will not compile due to inadequacies of C++.
Just FYI, since in this case you are using only a struct(ure), it is the same behavior as in C language.
Though this is a language feature, it is recommended that it shall not be used
I do not agree and NOT RECOMMEND to return vector to change values: Is much faster pass as reference:
void vectorial(vector <double> a, vector <double> b, vector <double> &c)
{
c[0] = a[1] * b[2] - b[1] * a[2]; c[1] = -a[0] * b[2] + b[0] * a[2]; c[2] = a[0] * b[1] - b[0] * a[1];
}
//This is slow!!!:
vector <double> vectorial(vector <double> a, vector <double> b)
{
vector <double> c{ a[1] * b[2] - b[1] * a[2], -a[0] * b[2] + b[0] * a[2], a[0] * b[1] - b[0] * a[1] };
return c;
}
I tested on VS2015 with following results in release mode:
By reference:8.01 MOPs and returning vector: 5.09 MOPs 60% worse!
In debug mode things are much worse:
By reference:0.053 MOPS and return vector: 0.034 MOPs
참고URL : https://stackoverflow.com/questions/1529447/does-return-statement-copy-values
'programing tip' 카테고리의 다른 글
두 개의 TextView가 나란히 있고 하나만 타원 크기입니까? (0) | 2020.11.22 |
---|---|
C # ASP.NET MVC 이전 페이지로 돌아 가기 (0) | 2020.11.22 |
Angular 2-하위 모듈 라우팅 및 중첩 (0) | 2020.11.22 |
대부분의 STL 구현의 코드가 왜 그렇게 복잡합니까? (0) | 2020.11.22 |
ASP .NET MVC의 web.config에서 TargetFramework 설정은 무엇을 의미합니까? (0) | 2020.11.22 |