
1. Switch 문에 default 라벨이 없는 경우
2. switch 문에 의도를 알기 어려운 fallthrough가 존재할 경우
3. range-based for문에서의 높은 비용의 복사 시
4. auto 키워드와 함께 높은 비용의 복사 시
위와 같은 4가지의 경우에 경고를 발생한다.
switch (val)
{
case 1:
std::cout<<"1";
break;
case 2:
std::cout<<"2";
break;
}
switch (val)
{
case 1:
std::cout<<"1";
break;
case 2:
case 3: // warning
std::cout<<"this is";
// [[fallthrough]]
case 4:
std::cout<<"2";
break;
}
void emailEvertoneInCompany(const std::vector<Person>& employees)
{
Email email;
for(Person p : employees)
{
// Warning C26817: Potentially expensive copy of variable 'p' in range-for loop.
email.addRecipient(p.email_address);
}
void emailEvertoneInCompany(const std::vector<Person>& employees)
{
Email email;
for(const Person& p : employees)
{
email.addRecipient(p.email_address);
}
이처럼 사용하면 복사를 하지 않는다.
근데 뭔가 형태가 너무 익숙하다 코딩하다보면 사실 범위 기반 for문을 돌게 되면 const auto& 가 기본으로 작성했는데, 복사때문인건 알고 있었지만 복사를 하게 되면 경고를 주는 것은 새롭게 알게 된 것 같다.
여기서 의문인것은 "높은 비용"이다. "높은 비용"의 기준이 무엇일까?
-> 크기가 플랫폼 종속 포인터 크기의 두배보다 크고 스마트 포인터나 gsl::span,gsl::string_spanstd::string_viewPerson이 아닌 경우 복사본의 비용이 많이 드는 것으로 간주한다.
즉, 숫자, 스칼라 등과 같은 작은 데이터 유형의 경우에는 경고가 발생하지 않는다.
추가적으로 루프 안에서 변수의 변경이 일어나면 검사가 실시되지 않는다. 유의해야한다. 복사가 일어나므로 변수의 변경을 실시하는 경우는 복사된 값의 변경이라 이런 방식으로 사용하는 일은 거의 없다고 생각한다. 결론은 꼭 참조를 붙이자~
class PasswordManager
{
std::string password;
public:
const std::string& getPassword() const
{ return password;}
};
void stealPassword(const PasswordManager& pm)
{
// Warning C26820: Assigning by value when a const-reference would suffice,
// use const auto& instead.
auto password = pm.getPassword();
}
위 클래스는 getPassword는 const 참조 타입을 반환한다. stealPassword 함수에서 auto 키워드로 pm의 객체를 받는다. 컴파일러는 password가 참조로 받을지 값으로 받을지 판단하지 못한다. 하지만 이는 수정하지도 않고 그냥 받아오는 경우는 복사가 일어나고 위에 언급했던 "높은 비용" 이 발생하면 경고를 발생한다.
이러한 경고는 const 참조가 효율적이라 판단해 const auto&로 받도록 하는 것이다.