【问题标题】:C++, return const and non const reference to std::set itemC++,返回对 std::set 项的 const 和非 const 引用
【发布时间】:2012-01-24 22:31:29
【问题描述】:

有一个类A包含两个重载方法getItems();

typedef std::vector <int> TItems;

template <typename T>
class A 
{
private:
    T a;
    TItems items;

public:
    A(){}
    A ( const T a_, const TItems & items_) : a(a_) , items (items_) {}
    bool operator () ( const A <T> &aa ) {return a < aa.a;}
    TItems const & getItems() const {return items}
    TItems & getItems() {return items}
};

和A对象的集合

template <typename T>
struct TSet {typedef std::set <A <T> > Type;};

我想返回 const 引用/对 TItems 的引用,但只有第二种方法有效

int main ()
{
TSet <double> ::Type t;
TSet <double> ::Type::iterator it = t.begin();
t.insert (A <double>( 5, TItems(10,10)));

const TItems *items = &(it->getItems()); //OK
TItems *items = &(it->getItems()); //Error  
}

Error   1   error C2440: 'initializing' : cannot convert from 'const TItems *' to 'TItems *

这是非常量引用能够修改 A 对象导致集合的潜在重新排列的原因吗?但是集合中的项目不是按 A.items 排列而是按 a.

有没有办法使用非常量引用修改 A.items?

【问题讨论】:

    标签: c++ reference set constants


    【解决方案1】:

    这是非常量引用能够修改 A 对象导致集合的潜在重排的原因吗?

    没错。 std::set 的元素(和 BTW std::map 的键)是不可变的,该结构只会给你 const 限定的元素。所以你有选择

    • 将结构更改为std::map,并将a 作为键,items 作为数据
    • 如果您绝对确定不会通过items 操作来破坏排序,您可以const_cast(或声明items mutable,如果适合您)。

    【讨论】:

    • 从技术上讲,const_cast 是用于此目的的 UB(即使我在保证自己订购的情况下使用它是有罪的),mutable 在这里没有任何改变。不,没有出路:如果您允许用户潜在地破坏排序,那么您首先不应该使用set
    • @AlexandreC。如果您从集合元素中删除 const 并且只更改不用于排序的成员,请详细说明为什么会发生未定义的行为?例如,您可以将用于排序的成员声明为 const。这并不意味着整个 set 元素必须是 const。
    【解决方案2】:

    如果您被允许更改集合元素,您可能会破坏实现集合的结构的不变量(例如平衡搜索树)。因此,集合的元素必须是不可变的。所以如果你想修改一个元素,你必须删除一个元素并用一个新元素替换它。特别是,您不能期望通过迭代器对set 进行非常量引用(如果您可以修改它,您可能会破坏排序)。 .

    【讨论】:

      【解决方案3】:

      您不能更改存储在 std::set 中的对象,因为这会破坏集合的不变量。相反,您可以从集合中移除对象,然后对其进行修改并再次插入。

      另一种可能性是使用 std::map 代替。 map的key不能修改,value可以修改。

      【讨论】:

      • 如果您参考第一个选项,那么您可以制作一个副本,将其从集合中删除,修改该副本并将其插入集合中。
      猜你喜欢
      • 2012-08-28
      • 1970-01-01
      • 2018-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 2015-06-10
      • 1970-01-01
      相关资源
      最近更新 更多