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
'IT TIP' 카테고리의 다른 글
GNU 화면이 응답하지 않고 차단 된 것 같습니다. (0) | 2020.10.15 |
---|---|
JavaScript에서 URL 구문 분석 (0) | 2020.10.15 |
업데이트 된 APK를 수동으로 설치하면 '서명이 이전에 설치된 버전과 일치하지 않습니다.'와 함께 실패합니다. (0) | 2020.10.15 |
HTTPClient 응답에서 GZip 스트림 압축 해제 (0) | 2020.10.15 |
선택기 'my-app'이 어떤 요소와도 일치하지 않습니다. (0) | 2020.10.15 |