오류 : xxx를 'this'인수로 xxx를 전달하면 한정자를 버립니다.


456
#include <iostream>
#include <set>

using namespace std;

class StudentT {

public:
    int id;
    string name;
public:
    StudentT(int _id, string _name) : id(_id), name(_name) {
    }
    int getId() {
        return id;
    }
    string getName() {
        return name;
    }
};

inline bool operator< (StudentT s1, StudentT s2) {
    return  s1.getId() < s2.getId();
}

int main() {

    set<StudentT> st;
    StudentT s1(0, "Tom");
    StudentT s2(1, "Tim");
    st.insert(s1);
    st.insert(s2);
    set<StudentT> :: iterator itr;
    for (itr = st.begin(); itr != st.end(); itr++) {
        cout << itr->getId() << " " << itr->getName() << endl;
    }
    return 0;
}

줄을 :

cout << itr->getId() << " " << itr->getName() << endl;

다음과 같은 오류가 발생합니다.

../main.cpp:35 : 오류 : 'const StudentT'를 'int StudentT :: getId ()'의 'this'인수로 전달하면 한정자가 삭제됩니다.

../main.cpp:35 : 오류 : 'const StudentT'를 'std :: string StudentT :: getName ()'의 'this'인수로 전달하면 한정자가 삭제됩니다.

이 코드에 어떤 문제가 있습니까? 감사합니다!


13
코드 스 니펫의 35 행은 어디에 있습니까?
silico에서

117
GCC가 "
discards

13
@ jfritz42 : 폐기 사건에 대해 혼란 스러울 것입니다volatile
PlasmaHH

3
@PlasmaHH 오류 메시지는 "정확한 구성을 위반합니다"와 "휘발성을 위반하는 것"으로 나뉩니다. 이제는 휘발성이
Caleth

답변:


524

의 객체 std::set는로 저장됩니다 const StudentT. 그래서 당신은 전화를 할 때 getId()const주로가 아닌 const 멤버 함수는 NO 약속 개체를 수정하지 수 있도록하기 때문에 허용되지 않습니다 const를 객체의 비 const 멤버 함수를 호출하고, 컴파일러가 문제를 감지 개체; 따라서 컴파일러는 객체를 수정하려고 시도 하는 동시에 안전한 것으로 가정 getId()하지만 동시에 객체가 const임을 알 수 있습니다. 따라서 const 객체를 수정하려고 시도하면 오류가 발생합니다. 따라서 컴파일러는 오류 메시지를 생성합니다.

해결책은 간단합니다. 함수를 다음과 같이 구성하십시오.

int getId() const {
    return id;
}
string getName() const {
    return name;
}

const 객체를 다음과 같이 호출 getId()하고 호출 할 수 있기 때문에 필요 getName()합니다.

void f(const StudentT & s)
{
     cout << s.getId();   //now okay, but error with your versions
     cout << s.getName(); //now okay, but error with your versions
}

참고로 다음과 같이 구현해야합니다 operator<.

inline bool operator< (const StudentT & s1, const StudentT & s2)
{
    return  s1.getId() < s2.getId();
}

참고 매개 변수는 이제 const참조입니다.


3
그런 명확한 설명. 감사. 그러나 마지막 코드 스 니펫이 궁금합니다. 함수 매개 변수에서 참조를 사용하는 이유는 무엇입니까? const StudentT & s1, const StudentT & s2?
Rafael Adel

2
@ RafaelAdel : 불필요한 복사를 피하기 위해 참조를 사용 const하고 함수가 객체를 수정할 필요가 없으므로 const컴파일 타임에 강제로 적용합니다.
Nawaz 2016 년

90

클래스 인스턴스를 수정하지 않는 멤버 함수는 다음과 같이 선언해야합니다 const.

int getId() const {
    return id;
}
string getName() const {
    return name;
}

"discards 한정자"가 표시 될 때마다 const또는 에 대해 이야기하고 volatile있습니다.


2
@Fred-클래스 인스턴스를 수정하지 않는 멤버 함수에 const 한정자를 추가해야한다고 생각하십니까? 이 경우 오류의 다른 이유가 있습니까? 필자가 작성한 대부분의 게터에서 const 한정자를 추가하지 않기 때문에 의심합니다.
Mahesh

@Mahesh : 예, const 정확성 의 일부입니다 . 나는 어디에서 오는지 확실하지 const않지만 set인스턴스가 변경되어 세트가 무효화되는 것을 막기 위해 반복자에서 const 참조를 반환한다고 생각합니다 .
Fred Larson

@Mahesh : 내 코드 검토를 통과하지 못했습니다. 저를 "불변"이라고 말하는 동료가 있습니다. 8V) 변경 그 foo obj;에게 const foo obj;한 번 무슨 일이 일어 나는지. 또는에 대한 const참조를 전달하십시오 foo.
Fred Larson

3
@Mahesh : 내가 말한 것처럼-a의 요소 set가 변경되면 순서가 화가 나고 더 이상 세트가 유효하지 않습니다. A의 map만 키입니다 const. A의 set전체 목적은 정말 중요합니다.
프레드 라슨

1
@Mahesh : const가 필요합니다. 그렇지 않으면 const 객체로 호출 할 수 없습니다. f()내 답변 에서 기능 을 참조하십시오 .
Nawaz

5

실제로 C ++ 표준 (예 : C ++ 0x draft )은 말합니다 (tnx ~ @Xeo & @Ben Voigt).

23.2.4 연관 컨테이너
5 설정 및 다중 설정의 경우 값 유형은 키 유형과 동일합니다. 맵 및 멀티 맵의 경우 쌍과 같습니다. 연관 컨테이너의 키는 변경할 수 없습니다. 연관 컨테이너의
6 반복자는 양방향 반복기 범주입니다. 값 유형이 키 유형과 동일한 연관 컨테이너의 경우 반복자 및 const_iterator는 모두 상수 반복자입니다. iterator와 const_iterator가 동일한 유형인지 여부는 지정되지 않았습니다.

따라서 VC ++ 2008 Dinkumware 구현에 결함이 있습니다.


이전 답변 :

std lib의 특정 구현 set::iterator에서와 동일 하기 때문에 오류가 발생 했습니다 set::const_iterator.

예를 들어 libstdc ++ (g ++로 제공)에는 다음이 있습니다 ( 전체 소스 코드는 여기 참조 ).

typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

그리고 SGI의 문서 에는 다음과 같이 명시되어 있습니다.

iterator       Container  Iterator used to iterate through a set.
const_iterator Container  Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.)

반면에 VC ++ 2008 Express는 비 const 메소드를 호출한다고 불평하지 않고 코드를 컴파일합니다 set::iterator.


2

좀 더 자세한 예를 들어 보겠습니다. 아래 구조체에 관해서 :

struct Count{
    uint32_t c;

    Count(uint32_t i=0):c(i){}

    uint32_t getCount(){
        return c;
    }

    uint32_t add(const Count& count){
        uint32_t total = c + count.getCount();
        return total;
    }
};

여기에 이미지 설명을 입력하십시오

위와 같이 IDE (CLion)에 대한 정보가 Non-const function 'getCount' is called on the const object있습니다. 메소드 add count에서 const 객체로 선언되었지만 메소드 getCount가 const 메소드가 아니므로 count.getCount()의 멤버를 변경할 수 있습니다 count.

아래와 같이 오류를 컴파일하십시오 (컴파일러의 핵심 메시지) :

error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]

위의 문제를 해결하려면 다음을 수행하십시오.

  1. 방법 uint32_t getCount(){...}을로 변경하십시오 uint32_t getCount() const {...}. 따라서 count.getCount()의 멤버를 변경하지 않습니다 count.

또는

  1. 로 변경 uint32_t add(const Count& count){...}하십시오 uint32_t add(Count& count){...}. 따라서 count멤버 변경에 신경 쓰지 마십시오.

당신이 문제에 관해서는, 세트가 StudentT CONST로 저장됩니다 :: 성병에 객체 있지만, 방법을 getId그리고 getName당신이 위의 오류를 줄 수 있도록,하지 CONST 있습니다.

또한이 질문을 볼 수 있습니다 클래스의 함수 선언에서 마지막 'const'의 의미? 자세한 내용은.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.