Неверное преобразование из «const int *» в «int *» при получении адреса элемента std :: set - PullRequest
5 голосов
/ 18 октября 2011

Я получаю следующую ошибку error: invalid conversion from ‘const int*’ to ‘int*’ Ниже моя программа

#include <set>
int main ( int argc, char **argv) {
    std::set<int> intSet;
    intSet.insert(1);
    intSet.insert(2);
    intSet.insert(3);
    intSet.insert(4);
    intSet.insert(5);

    int *pAddress = &(*(intSet.find(4)));
}

Я хочу адрес элемента в std::set, этот код не выдает никакой ошибки компиляции с помощью компилятора Microsoft, но g++ выдает эту ошибку компиляции.

Ответы [ 3 ]

5 голосов
/ 18 октября 2011

Это потому, что каждый элемент std::set хранится как T const, и реализация имеет причину для этого.

Поскольку std::set содержит ровно одну копию значения. Он должен сделать его неизменным , иначе можно изменить его значение на то, что уже существует в наборе.

Даже если бы элементы были mutable , вы не смогли бы изменить значение, потому что std::set::find является const функцией-членом, и поэтому в этой функции intSet равно неизменный , и фактически каждый элемент станет неизменным , включая итератор , который он возвращает, и через который вы можете изменить значение при вызове -site.

Единственный, кто хочет получить адрес, это:

int const *paddress =  &(*(intSet.find(4))); //const int* is same as int const*

Не используйте const_cast хотя,

//DANGEROUS - DONT DO IT
int *paddress =  const_cast<int*>(&(*(intSet.find(4)))); //will compile, 
                                                       //but it is dangerous!

//you might accidentally write
*paddress = 10; //undefined behaviour, 
                //though the compiler will let you write this
1 голос
/ 18 октября 2011

GCC определяет set::iterator как set::const_iterator, предотвращая привязку не const ссылки или указателя к результату set::find().Это поведение разрешено в C ++ 11 (в котором говорится, что ключи являются неизменяемыми, и что set::iterator является постоянным итератором), но в C ++ 03 было неверно.не должен изменять элементы набора, так как это может нарушить порядок элементов в нем.В некоторых случаях вы можете захотеть - если тип является классом, и только некоторые члены используются для определения порядка, тогда было допустимо изменить другие члены.Стандарт C ++ 03 допускает это, но вы должны быть осторожны, чтобы не изменять порядок, поскольку это приведет к неопределенному поведению.В C ++ 11 это не разрешено, и реализация может предотвратить это.

В вашем случае вы вообще не можете юридически изменить значение, поэтому вы можете исправить свой код для C ++11, а также повысить его безопасность, привязав указатель к константе.

int const *pAddress = &(*(intSet.find(4)));
0 голосов
/ 18 октября 2011

Значения набора должны быть неизменными, чтобы класс мог гарантировать, что все элементы уникальны. Если вы укажете не const указатель, это будет слишком просто для вас, чтобы изменить значение, что нарушит дизайн класса установленного шаблона

Вы должны изменить последнюю строку, чтобы перед ней стояло "const", например:

const int *pAddress = &(*(intSet.find(4)));

К вашему сведению: ваш код выдает ту же ошибку компиляции в Visual Studio 2010.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...