在接受std::set元素地址时,从' const int* '到' int* '的转换无效

Invalid conversion from ‘const int*’ to ‘int*’ while taking std::set element address

本文关键字:int const 无效 转换 std set 元素 地址      更新时间:2023-10-16

我得到以下错误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++给出了这个编译错误。

这是因为std::set的每个元素都被存储为T const,并且实现有理由这样做。

因为std::set只包含一个值的一个副本。它必须使不可变,否则,可以将它的值更改为集合中已经存在的值。

即使元素是可变的,你也不能改变值,因为std::set::findconst成员函数,因此在这个函数中intSet不可变的,实际上每个元素也会变成不可变的,包括它返回的迭代器,通过可以在调用点改变值。

唯一要取的地址是:

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

GCC将set::iterator定义为set::const_iterator,防止将非const引用或指针绑定到set::find()的结果。此行为在c++ 11中是允许的(声明键是不可变的,并且set::iterator是常量迭代器),但在c++ 03中是不正确的。

在c++ 03中,不应该修改集合的元素,因为这会破坏集合中元素的顺序。在某些情况下,您可能希望—如果类型是一个类,并且只有一些成员用于定义排序,那么修改其他成员是有效的。c++ 03标准允许这样做,但您必须小心不要修改顺序,因为这会产生未定义的行为。在c++ 11中,这是不允许的,并且实现可能会阻止这一点。

在你的例子中,你根本不能合法地修改这个值,所以你可以为c++ 11修改你的代码,并通过绑定到指向const的指针来提高它的安全性。

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

集合的值是不可变的,这样类就可以保证所有元素都是唯一的。给你一个非const的指针会让你很容易改变值,这会破坏set模板类的设计(http://msdn.microsoft.com/en-us/library/e8wh7665(VS.80).aspx)。

你应该改变最后一行,在它前面加一个"const",像这样:

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

仅供参考:您的代码在Visual Studio 2010中给出了相同的编译错误。