IT TIP

const 객체를 반환해야합니까?

itqueen 2020. 10. 15. 22:09
반응형

const 객체를 반환해야합니까?


에서 Effective C++항목 03, 사용 가능한에서 const.

class Bigint
{
  int _data[MAXLEN];
  //...
public:
  int& operator[](const int index) { return _data[index]; }
  const int operator[](const int index) const { return _data[index]; }
  //...
};

const int operator[]에서 메이크업의 차이를 않습니다 int& operator[].

하지만 어떨까요?

int foo() { }

const int foo() { }

그들은 같은 것 같습니다.

내 질문은 왜 우리가 const int operator[](const int index) const대신 사용 int operator[](const int index) const합니까?


비 클래스 유형의 리턴 유형에 대한 최상위 레벨 cv 한정자는 무시됩니다. 즉, 다음과 같이 작성하더라도 다음을 의미합니다.

int const foo();

반환 유형은 int입니다. 물론 반환 유형이 참조 인 경우 const는 더 이상 최상위 수준이 아니며 다음과 같은 차이점이 있습니다.

int& operator[]( int index );

int const& operator[]( int index ) const;

중요합니다. (위와 같이 함수 선언에서 최상위 레벨 cv 한정자도 무시됩니다.)

이 구분은 클래스 유형의 반환 값과도 관련이 있습니다.을 반환 T const하면 호출자는 반환 된 값에 대해 상수가 아닌 함수를 호출 할 수 없습니다. 예 :

class Test
{
public:
    void f();
    void g() const;
};

Test ff();
Test const gg();

ff().f();             //  legal
ff().g();             //  legal
gg().f();             //  **illegal**
gg().g();             //  legal

반환 값, 매개 변수 및 함수 자체에 적용되는 const 사용을 명확하게 구분해야합니다.

반환 값

  • 함수가 value 로 반환되면 객체의 복사본이 반환되므로 const는 중요하지 않습니다. 그러나 이동 의미가 포함 된 C ++ 11에서는 중요합니다.
  • 기본 유형은 항상 복사되므로 중요하지 않습니다.

고려하십시오 const std::string SomeMethod() const. (std::string&&)상수가 아닌 rvalue를 예상 하므로 함수를 사용할 수 없습니다 . 즉, 반환 된 문자열은 항상 복사됩니다.

  • 함수가 반환하는 경우 참조 , const수정되는 반환 된 객체를 보호합니다.

매개 변수

  • 으로 매개 변수를 전달 하면 const는 함수의 함수 의해 주어진 값이 수정되는 것을 방지합니다 . 복사본 만 있기 때문에 매개 변수의 원본 데이터는 수정할 수 없습니다.
  • 복사본은 항상 생성되기 때문에 const는 function body에 대한 의미 만 가지 므로 선언 (인터페이스)이 아닌 함수 정의에서만 확인됩니다.
  • 참조 로 매개 변수를 전달하면 반환 값과 동일한 규칙이 적용됩니다.

기능 자체

  • 함수가 const끝에 있으면 다른 const함수 만 실행할 수 있으며 클래스 데이터를 수정하거나 수정할 수 없습니다. 따라서 참조로 반환되는 경우 반환되는 참조는 const 여야합니다. const 함수 만 객체 또는 const 자체 인 객체에 대한 참조에서 호출 될 수 있습니다. 또한 변경 가능한 필드를 변경할 수 있습니다.
  • 컴파일러에 의해 생성 된 동작은 this참조를 T const*. 이 함수는 항상 할 수 const_cast this있지만 물론이 작업을 수행해서는 안되며 안전하지 않은 것으로 간주됩니다.
  • 물론 클래스 메서드에서만이 지정자를 사용하는 것이 합리적입니다. 끝에 const가있는 전역 함수는 컴파일 오류를 발생시킵니다.

결론

메서드가 클래스 변수를 수정하지 않고 절대로 수정하지 않는 경우이를 const로 표시하고 필요한 모든 기준을 충족해야합니다. 더 깨끗한 코드를 작성할 수 있으므로 const-correct 를 유지할 수 있습니다. 그러나 const아무 생각도하지 않고 어디에나 두는 것은 확실히 갈 길이 아닙니다.


비 참조 / 비 포인터 rvalue에 자격을 추가하는 데는 별 가치없으며 내장에 추가 할 필요도 없습니다 .const

의 경우에 , 사용자 정의 형 하는 const자격 호출자 막을 비 호출 const멤버 함수를 반환 개체. 예를 들어, 주어진

const std::string foo();
      std::string bar();

그때

foo().resize(42);

금지되는 반면

bar().resize(4711);

허용됩니다.

와 같은 내장 기능의 경우 int이러한 rvalue는 어쨌든 수정할 수 없기 때문에 전혀 의미가 없습니다.

(하지만 효과적인 C ++operator=() 에서 const참조 의 반환 유형을 만드는 데 대해 논의한 것을 기억 합니다. 이것은 고려해야 할 사항입니다.)


편집하다:

Scott이 실제로 그 조언을 한 것 같습니다 . 그렇다면 위에 주어진 이유 때문에 C ++ 98 및 C ++ 03에서도 의심 스럽습니다 . C ++ 11의 경우 Scott 자신이 발견 한 것처럼 분명히 잘못되었다고 생각합니다 . 대한 정오표 효과적인 C ++, 3 에디션. , 그는 다음과 같이 씁니다 (또는 불평 한 다른 사람을 인용합니다).

텍스트는 모든 값별 반환 값이 const 여야 함을 의미하지만, 상수가 아닌 값별 반환 값이 좋은 디자인 인 경우 찾기가 어렵지 않습니다. 예를 들어 호출자가 빈 벡터로 스왑을 사용하는 std :: vector 반환 유형 반환 값 내용을 복사하지 않고 "잡기".

그리고 나중에 :

값별 함수 반환 값 const를 선언하면 C ++ 0x의 rvalue 참조에 바인딩되지 않습니다. rvalue 참조는 C ++ 코드의 효율성을 향상시키기 위해 설계되었으므로 함수 서명을 지정할 때 const 반환 값의 상호 작용과 rvalue 참조의 초기화를 고려하는 것이 중요합니다.


마이어스의 조언을 놓칠 수도 있습니다. 근본적인 차이점은 const방법에 대한 수정 자입니다.

This one is a non-const method (notice no const at the end) which means it is allowed to modify the state of the class.

int& operator[](const int index)

This one is a const method (notice const at the end)

const int operator[](const int index) const

What about types of the parameter and the return value, there is a minor difference between int and const int, but it is not relevant to the point of the advice. What you should pay attention to that the non-const overload returns int& which means you can assign to it, e.g. num[i]=0, and the const overload returns non-modifiable value (no matter if the return type is int or const int).

In my personal opinion, if an object is passed by value, const modifier is superfluous. This syntax is shorter and achieves the same

int& operator[](int index);
int operator[](int index) const;

The primary reason for returning values as const is so that you can't say something like foo() = 5;. This isn't actually an issue with primitive types, since you can't assign to rvalues of primitive types, but it is an issue with user-defined types (like (a + b) = c;, with an overloaded operator+).

I've always found the justification for that rather flimsy. You can't stop someone who's intent on writing awkward code, and this particular type of coercion has no real benefit in my opinion.

With C++11, there's actually a good deal of harm this idiom is doing: Returning values as const prevents move optimisations and should thus be avoided whenever possible. Basically, I'd now consider this an anti-pattern.

Here's a tangentially related article concerning C++11.


When that book was written, the advice was of little use, but did serve to prevent the user writing, for example, foo() = 42; and expecting it to change something persistent.

In the case of operator[], this can be slightly confusing if you don't also provide a non-const overload that returns a non-const reference, although you can perhaps prevent that confusion by returning a const reference or a proxy object instead of a value.

These days, it's bad advice, since it prevents you from binding the result to a (non-const) rvalue reference.

(As pointed out in the comments, the question is moot when returning a primitive type like int, since the language prevents you from assigning to an rvalue of such a type; I'm talking about the more general case that includes returning user-defined types.)


For primitive types (like int), the const-ness of the result does not matter. For classes, it might change the behaviour. For example, you might not be able to call a non-const method on the result of your function:

class Bigint {
    const C foo() const { ... }
     ...
}

Bigint b;
b.foo().bar();

The above is forbidden if bar() is a const member function of C. In general, choose whichever makes sense.


Look on that:

const int operator[](const int index) const

the const on end of statement. It describe that this method can be called on constants.

In the other hand when you write only

int& operator[](const int index)

it can be called only on non-const instances and also provide:

big_int[0] = 10;

syntax.


One of your overloads is returning a reference to an item in the array, which you are then able to change.

int& operator[](const int index) { return _data[index]; }

The other overload is returning a value for you to use.

const int operator[](const int index) const { return _data[index]; }

Since you call each of these overloads in the same way, and one will never change the value when it's used.

int foo = myBigInt[1]; // Doesn't change values inside the object.
myBigInt[1] = 2; // Assigns a new value at index `

In the example of the array-indexing operator (operator[]) it does make a difference.

With

int& operator[](const int index) { /* ... */ }

you can use the indexing to directly change the entry in the array, e.g. using it like this:

mybigint[3] = 5;

The second, const int operator[](const int) operator is used to fetch the value only.

However, as return value from functions, for simple types like e.g. int it doesn't matter. When it does matter is if you are returning more complex types, say a std::vector, and don't want the caller of the function to modify the vector.


The const return type is not so important here. Since int temporaries are not modifiable, there's no observable difference in using int vs const int. You would see a difference if you used a more complex object which could be modified.


There are some good answers revolving around the technicality of the two versions. For a primitive value, it doesn't make a difference.

However, I've always considered const to be there for the programmer rather than the compiler. When you write const, you're explicitly saying "this shouldn't change". Let's face it, const can usually be circumverted anyway, right?

When you return a const, you're telling the programmer that uses that function that the value shouldn't change. And if he is changing it, he's probably doing something wrong, because he/she shouldn't have to.

EDIT: I also think "use const whenever possible" is bad advice. You should use it where it makes sense.

참고URL : https://stackoverflow.com/questions/12051012/should-i-return-const-objects

반응형