Programing

C ++에서 값으로 전달하거나 상수 참조로 전달하는 것이 더 낫습니까?

lottogame 2020. 5. 7. 07:56
반응형

C ++에서 값으로 전달하거나 상수 참조로 전달하는 것이 더 낫습니까?


C ++에서 값으로 전달하거나 상수 참조로 전달하는 것이 더 낫습니까?

어느 쪽이 더 나은 방법인지 궁금합니다. 변수의 사본을 만들지 않기 때문에 상수 참조로 전달하면 프로그램의 성능이 향상되어야합니다.


그것은 일반적으로 가장 좋은 방법은 추천하는 데 사용 1대한 const를 심판하여 사용 패스 모든 종류의 유형 (내장을 제외하고 char, int, double반복자를 들어, 등), 함수 객체에 대한 (에서 파생 람다, 클래스 std::*_function).

이것은 이동 의미론 이 존재하기 전에 특히 그렇습니다 . 그 이유는 간단합니다. 값으로 전달하면 객체의 복사본을 만들어야했으며 매우 작은 객체를 제외하고는 참조를 전달하는 것보다 항상 비쌉니다.

C ++ 11을 사용하면 이동 의미를 얻었습니다 . 간단히 말해서 이동 의미론은 어떤 경우에는 객체를 복사하지 않고 "값으로"전달할 수 있도록합니다. 특히, 전달하는 객체가 rvalue 인 경우 입니다.

그 자체로 객체를 이동하는 것은 여전히 ​​참조로 전달하는 것만 큼 비싸다. 그러나 많은 경우 함수는 내부적으로 객체를 복사합니다. 즉 , 인수의 소유권 을 갖습니다. 2

이러한 상황에서 우리는 다음과 같은 (단순화 된) 장단점이 있습니다.

  1. 객체를 참조로 전달한 다음 내부적으로 복사 할 수 있습니다.
  2. 값으로 객체를 전달할 수 있습니다.

객체가 rvalue가 아닌 한 "값별 패스"는 여전히 객체를 복사합니다. rvalue의 경우 객체를 대신 이동할 수 있으므로 두 번째 경우가 더 이상 "복사, 이동"하지 않고 "이동 한 다음 (잠재적으로) 다시 이동"합니다.

적절한 이동 생성자 (벡터, 문자열 등)를 구현하는 큰 객체의 경우 두 번째 경우는 첫 번째보다 훨씬 효율적입니다. 따라서 함수가 인수의 소유권을 가지며 객체 유형이 효율적인 이동을 지원하는 경우 값으로 전달사용 하는 것이 좋습니다 .


역사적 메모 :

실제로 모든 최신 컴파일러는 값으로 전달하는 것이 비쌀 때 알아낼 수 있어야하며 가능하면 const 참조를 사용하도록 호출을 암시 적으로 변환해야합니다.

이론에 의하면. 실제로 컴파일러는 함수의 이진 인터페이스를 중단하지 않고 항상 이것을 변경할 수는 없습니다. 일부 특수한 경우 (함수가 인라인 될 때) 컴파일러가 함수의 조치를 통해 원래 오브젝트가 변경되지 않음을 알 수있는 경우 사본이 실제로 제거됩니다.

그러나 일반적으로 컴파일러는 이것을 결정할 수 없으며 C ++에서 이동 의미의 출현으로 인해이 최적화가 훨씬 덜 적합 해졌습니다.


1 예 : Scott Meyers의 효과적인 C ++ .

2 이것은 객체 생성자의 경우에 특히 그렇습니다. 인수는 인수를 받아서 내부에 생성 된 객체 상태의 일부로 저장할 수 있습니다.


편집 : cpp-next의 Dave Abrahams의 새 기사 :

속도를 원하십니까? 값으로 전달하십시오.


복사가 저렴한 구조체의 값으로 전달하면 컴파일러가 객체가 별칭이 아닌 것으로 간주 할 수 있다는 추가 이점이 있습니다 (동일한 객체가 아님). 패스 바이 레퍼런스를 사용하면 컴파일러는 항상이를 가정 할 수 없습니다. 간단한 예 :

foo * f;

void bar(foo g) {
    g.i = 10;
    f->i = 2;
    g.i += 5;
}

컴파일러는 그것을 최적화 할 수 있습니다

g.i = 15;
f->i = 2;

f와 g가 같은 위치를 공유하지 않는다는 것을 알고 있기 때문입니다. g가 참조 (foo &) 인 경우 컴파일러는이를 가정 할 수 없었습니다. gi는 f-> i로 별칭을 지정할 수 있고 값은 7이어야하므로 컴파일러는 메모리에서 새로운 gi 값을 다시 가져와야합니다.

보다 실용적인 규칙을 보려면 Move Constructors 기사 (권장 사항) 에서 찾아 볼 수있는 규칙이 있습니다.

  • 함수가 인수를 부작용으로 변경하려는 경우, 상수가 아닌 참조로 가져 가십시오.
  • If the function doesn't modify its argument and the argument is of primitive type, take it by value.
  • Otherwise take it by const reference, except in the following cases
    • If the function would then need to make a copy of the const reference anyway, take it by value.

"Primitive" above means basically small data types that are a few bytes long and aren't polymorphic (iterators, function objects, etc...) or expensive to copy. In that paper, there is one other rule. The idea is that sometimes one wants to make a copy (in case the argument can't be modified), and sometimes one doesn't want (in case one wants to use the argument itself in the function if the argument was a temporary anyway, for example). The paper explains in detail how that can be done. In C++1x that technique can be used natively with language support. Until then, i would go with the above rules.

Examples: To make a string uppercase and return the uppercase version, one should always pass by value: One has to take a copy of it anyway (one couldn't change the const reference directly) - so better make it as transparent as possible to the caller and make that copy early so that the caller can optimize as much as possible - as detailed in that paper:

my::string uppercase(my::string s) { /* change s and return it */ }

However, if you don't need to change the parameter anyway, take it by reference to const:

bool all_uppercase(my::string const& s) { 
    /* check to see whether any character is uppercase */
}

However, if you the purpose of the parameter is to write something into the argument, then pass it by non-const reference

bool try_parse(T text, my::string &out) {
    /* try to parse, write result into out */
}

Depends on the type. You are adding the small overhead of having to make a reference and dereference. For types with a size equal or smaller than pointers that are using the default copy ctor, it would probably be faster to pass by value.


As it has been pointed out, it depends on the type. For built-in data types, it is best to pass by value. Even some very small structures, such as a pair of ints can perform better by passing by value.

Here is an example, assume you have an integer value and you want pass it to another routine. If that value has been optimized to be stored in a register, then if you want to pass it be reference, it first must be stored in memory and then a pointer to that memory placed on the stack to perform the call. If it was being passed by value, all that is required is the register pushed onto the stack. (The details are a bit more complicated than that given different calling systems and CPUs).

If you are doing template programming, you are usually forced to always pass by const ref since you don't know the types being passed in. Passing penalties for passing something bad by value are much worse than the penalties of passing a built-in type by const ref.


This is what i normally work by when designing the interface of a non-template function:

  1. Pass by value if the function does not want to modify the parameter and the value is cheap to copy (int, double, float, char, bool, etc... Notice that std::string, std::vector, and the rest of the containers in the standard library are NOT)

  2. Pass by const pointer if the value is expensive to copy and the function does not want to modify the value pointed to and NULL is a value that the function handles.

  3. Pass by non-const pointer if the value is expensive to copy and the function wants to modify the value pointed to and NULL is a value that the function handles.

  4. Pass by const reference when the value is expensive to copy and the function does not want to modify the value referred to and NULL would not be a valid value if a pointer was used instead.

  5. Pass by non-const reference when the value is expensive to copy and the function wants to modify the value referred to and NULL would not be a valid value if a pointer was used instead.


Sounds like you got your answer. Passing by value is expensive, but gives you a copy to work with if you need it.


As a rule passing by const reference is better. But if you need to modify you function argument locally you should better use passing by value. For some basic types the performance in general the same both for passing by value and by reference. Actually reference internally represented by pointer, that is why you can expect for instance that for pointer both passing are the same in terms of performance, or even passing by value can be faster because of needless dereference.


As a rule of thumb, value for non-class types and const reference for classes. If a class is really small it's probably better to pass by value, but the difference is minimal. What you really want to avoid is passing some gigantic class by value and having it all duplicated - this will make a huge difference if you're passing, say, a std::vector with quite a few elements in it.


Pass by value for small types.

Pass by const references for big types (the definition of big can vary between machines) BUT, in C++11, pass by value if you are going to consume the data, since you can exploit move semantics. For example:

class Person {
 public:
  Person(std::string name) : name_(std::move(name)) {}
 private:
  std::string name_;
};

Now the calling code would do:

Person p(std::string("Albert"));

And only one object would be created and moved directly into member name_ in class Person. If you pass by const reference, a copy will have to be made for putting it into name_.


Simple difference :- In function we have input and output parameter , so if your passing input and out parameter is same then use call by reference else if input and output parameter are different then better to use call by value .

example void amount(int account , int deposit , int total )

input parameter : account , deposit output paramteter: total

input and out is different use call by vaule

  1. void amount(int total , int deposit )

input total deposit output total

참고URL : https://stackoverflow.com/questions/270408/is-it-better-in-c-to-pass-by-value-or-pass-by-constant-reference

반응형