IT TIP

왜 어떤 사람들은“const T &”보다“T const &”를 선호합니까?

itqueen 2020. 12. 30. 19:59
반응형

왜 어떤 사람들은“const T &”보다“T const &”를 선호합니까?


그래서, 그 실현 const T&T const&동일하며, 둘 모두의 경우에 CONST의 T. 참조를 의미, 기준은 (참조 포인터와 달리 재 할당 할 수없는)도 일정하다. 나는 다소 제한된 경험에서 대부분의 C ++ 프로그래머가를 사용하는 것을 관찰 const T&했지만 T const&. 나는 const T&그렇게 배웠기 때문에 단순히 사용 T const&하고 나에게 조금 웃기게 보입니다. 사용하는 변형을 사용하는 이유는 무엇입니까? 코딩 표준에 따라 하나의 변형을 다른 변형보다 사용해야하는 조직에서 일하는 사람이 있습니까?

편집
답변에 따르면 둘 중 하나를 선택하는 이유 중 하나는 컴파일러처럼 읽을 것인지 (오른쪽에서 왼쪽으로) 또는 영어처럼 (왼쪽에서 오른쪽으로) 읽을 것인지 여부입니다. 컴파일러처럼 읽으면 "T const &"는 "& (참조) const (상수에 대한) T (T 유형)"로 읽습니다. 영어처럼 왼쪽에서 오른쪽으로 읽으면 "const T &"는 "참조 형식의 T 유형 상수 객체"로 읽습니다. 나는 그것을 영어 산문처럼 읽는 것을 선호하지만, 컴파일러가하는 방식으로 그것을 해석하는 의미를 확실히 볼 수 있습니다.

아무도 조직 또는 코딩 표준 질문에 답하지 않았지만 대부분의 조직은 일관성을 위해 노력할 수 있지만 다른 조직보다 하나를 요구하지 않는다고 강력하게 의심합니다.


어떤 사람들은 단순히 오른쪽에서 왼쪽으로 선언문을 읽는 것을 선호한다고 생각합니다. const아무것도없는 경우를 제외하고는 왼쪽 토큰에 적용되고 오른쪽 토큰에 적용됩니다. 따라서 const T&"except"절이 포함되며 아마도 더 복잡하다고 생각할 수 있습니다 (실제로는 둘 다 이해하기 쉽습니다).

비교:

const T* p;  (pointer to T that is const)
T const* p;  (pointer to const T) //<- arguable more natural to read
T* const p;  (const pointer to T)

이것은 하나 이상의 const / volatile 수정자가있을 때 차이를 만듭니다. 그런 다음 유형의 왼쪽에 두는 것은 여전히 ​​유효하지만 전체 선언의 일관성을 깨뜨릴 것입니다. 예를 들면 :

T const * const *p;

p는 const T에 대한 const 포인터에 대한 포인터이며 일관되게 오른쪽에서 왼쪽으로 읽습니다.

const T * const *p;

의미는 동일하지만 일관성이 손실되며 가장 왼쪽의 const / volatile은 T *가 아닌 T에만 바인딩된다는 것을 기억해야합니다.


이 토론이 흥미 롭다면 Dan Saks 의이 기사가 흥미로울 것입니다. 귀하의 질문을 직접적으로 다루지는 않지만 그가 선호하는 이유를 설명합니다.

VP const foo[];

...에

const VP foo[];

주어진 때문입니다

typedef void *VP;

위의 두 번째 예가 의미한다고 생각하도록 쉽게 오해 될 수 있습니다.

const void *foo[];  // Wrong, actually: void *const foo[];

그러나 첫 번째 예는 잘못 해석하기가 더 어렵습니다.


개인적 취향이라고 생각합니다. 두 변형 사이에는 차이가 없습니다.


코드는 주로 영어 기반이므로 프로그래머는 왼쪽에서 오른쪽으로 읽는 경향이 있으므로 const T&컴파일러가 내부에서 오른쪽에서 왼쪽으로 T const&읽는 곳에서 자연스럽게 읽으 므로 자연스럽게 읽습니다 (const T에 대한 참조).


내 추론은 다음과 같습니다.

"const T &"라고 쓰면 혀를 더 잘 굴리는 것 같지만 그렇게하면 모호한 "상수 T 참조"로 끝납니다. 나는 이것이 코드의 이해성에 문제를 일으킨다는 것을 두 번 이상 보아 왔는데, 이로 인해 경험이 거의없는 사람이라도 무언가의 의미 나 더 복잡한 유형을 선언하는 방법을 잘못 해석 할 수있었습니다.

지금은 어떤 예도 생각할 수 없지만 "T const &"대신 "const T &"를 사용하는 습관으로 인해 문제가 발생한 유형 선언 및 constness에 대한 질문에 여러 번 대답했습니다. 저도 그런 식으로 작성했고 프로젝트에서 코드 표준을 멘토링하고 작성하는 책임자 인 Sr. Developer가되었을 때 모든 사람에게 "T const &"를 사용하도록 강요 할 때 초급 개발자가 훨씬 더 쉽게 사용할 수 있다는 것을 알았습니다. 사소하고 신인 실수가이 코드가 컴파일되는 이유라고 생각합니다.


const T* t = f();
t = 0; // assignment to const?? - no, it is not the T* that is const, just the T.

컴파일러가하는 방식으로 읽는 법을 배우면 주어진 복합 유형이 무엇인지 이해하기가 훨씬 쉬워지고 필요할 때 복잡한 유형을 더 쉽게 선언 할 수 있습니다. 복잡한 유형으로 나는 다음과 같은 것에 대해 이야기하고 있습니다.

T const * const &

컴파일러가 오른쪽에서 왼쪽으로, 안쪽에서 바깥쪽으로 읽는다는 것을 알면 그 의미가 매우 분명 해지고 하나를 작성해야 할 때 쉽게 할 수 있습니다. 상수 T에 대한 상수 포인터에 대한 참조 이제 a 선언을 작성하십시오. "T에 대한 상수 포인터에 대한 포인터에 대한 참조". 단순히 왼쪽에서 오른쪽으로 표기법을 사용하면이 작업이 매우 쉬울 것이라고 생각합니다.

간단히 말해서, 처음에는 필요할 때만 (종종 그렇기 때문에) 오른쪽-> 왼쪽 문법을 사용하도록 스스로 가르치는 것이 처음에는 부자연스러워 보이지만, 코드 줄이 의미하는 바를 훨씬 쉽게 기억할 수 있습니다. 그리고 당신이 의미하는 것을 쓰는 방법. 선언에서 ","를 허용하지 않는 이유와 같은 줄을 따릅니다.


T* ptr1 = 0, ptr2 = 0; // oops!!!

// do it this way please! T* ptr1 = 0; T* ptr2 = 0;

기술적으로는 모두 동일하지만 다양한 능력의 사람들이 동일한 작업을 수행하도록 시도 할 때 모든 사람이 가장 이해하고 사용하기 쉬운 방법을 사용하도록하는 경향이 있습니다. 내 경험을 통해 "T const &"가 그 방법이라는 것을 알게되었습니다.


일부는 오른쪽에서 왼쪽으로 선언을 읽는 것이 도움이되기 때문입니다.

char const*
const char*

둘 다 const char에 대한 포인터입니다.


나는 const T&논리적으로 왼쪽에서 오른쪽으로 읽기 때문에 강력하게 옹호 했습니다 ( 상수 T 참조입니다). (그리고 그 시점까지 만난 대부분의 코드가 그렇게 작성 되었기 때문에 약간의 편견이있을 것입니다.)

Over the years I've encountered some corner cases (such as multiple pointer/reference layers, multiple variable declarations, and method pointers) which strain things a little for the reasons other people have already answered. Often introducing additional typedefs help you "unstick" these cases to some extent, but then you have to come up with a name for something even if it's only used once.

The tipping point for me was the introduction of auto in C++11, especially when combined with range-based-for. With that, I've flipped and now strongly prefer T const& (or "reference to constant T", reading right to left) instead. Not only is it more consistent with how the compiler actually parses, it means that when you replace the type with auto, this always ends up at the left, which I think reads better.

Compare:

for (const T& a : list)         for (T& a : list)
for (T const& a : list)         for (T& a : list)
for (const auto& a : list)      for (auto& a : list)
for (auto const& a : list)      for (auto& a : list)

Note also the column on the right, where I've added the non-const version of the same. At least for me, the const vs. non-const and auto vs. explicit all seem most consistent in the cases where const appears after T.

But this is a style choice, and as such there is no absolutely correct answer.


If the const and & get far apart, as in

krog::FlamBlott<std::map<HurkleKey,Spleen<int>>
speckleFlams( const krog::Floonage & floon, const std::map<krog::HackleSpoon,std::vector<krog::HeckleObservation<OBSN>>> & obsmap);

krog::FlamFinagleReport
finagleFlams( const krog::Floonage & floon, std::map<krog::HackleSpoon,std::vector<krog::HeckleObservation<OBSN>>> & obsmap)

... 그러면 첫 번째 'obsmap'이 const 참조이고 두 번째가 아닌 것을 놓치기 쉽습니다.

참조 URL : https://stackoverflow.com/questions/2640446/why-do-some-people-prefer-t-const-over-const-t

반응형