2011-09-14 50 views
2
矢量

考虑下面的类:投STL ::包含指向STL ::含载体常指针

class SomeInfo 
{ 
private: 
    std::vector<someObj *> _myVector; 

public: 
    const std::vector<const someObj*>& getInfoVector() const 
    { 
     return _myVector; 
    } 
}; 

当我尝试用gcc 4.1.2编译,它给了我下面的错误:

error: invalid initialization of reference of type 
‘const std::vector<const someObj*, std::allocator<const someObj*> >&’ 
from expression of type 
‘const std::vector<someObj*, std::allocator<someObj*> > 

如果我删除'someObj *'前的'const',然后编译,但我不想用非常量指针返回向量,因为我不想让它们引用的对象从我的SomeInfo类外部改变。在这个情况下,你会怎么做?

+1

为什么不首先使_myVector成为常量指针的向量? – Ferruccio

+0

因为在后面阶段,会有一个析构函数,它必须'删除'常量指针,我知道这是允许的语言,但我认为它很丑陋!从我的观点来看,const是const的,不应该被触及......这个向量成员不是这种情况,它不是const,我只是想让const访问它的值。 – pinpinokio

回答

3

我会在这种情况下做的是忘记返回一个vector(或引用)。调用者不能进行任何更改,因此不需要查看任何特定的容器。其他答案解释了为什么你不能把你的向量看作是向量const someObj*。对于这个问题,如果将来您将班级更改为使用deque而不是vector,那么您无法返回对此的引用,就好像它也是一个向量。由于主叫方只需要访问的元素,让我们给他们说:

const someObj *getInfoAt(size_t n) const { 
    return _myVector.at(n); 
} 

const_info_iterator getInfoBegin() const { 
    return _myVector.begin(); 
} 

const_info_iterator getInfoEnd() const { 
    return _myVector.end(); 
} 

size_t getInfoSize() const { 
    return _myVector.size(); 
} 

// plus anything else they need. 

const_info_iterator是一个typedef的一类是有点烦写​​。它必须包装一个std::vector<someObj *>::const_iterator并且规定operator*的类型。 boost::transform_iterator可能是有用的,或从零开始编写并不是那么糟糕。不过,双向迭代器确实需要最多的运算符重载。

std::vector<const someObj*> mycopy(myinfo.getInfoBegin(), myinfo.getInfoEnd()); 

什么他们不能有一个vector,不断反映:现在

,如果主叫方真正想要的const someObj*,向量然后用我的界面,他们可以很容易地在任何特定时刻得到一个快照其他vector其他地方的变化 - std::vector只是不这样做。

+0

谢谢,史蒂夫,也许你的方法最符合我的需求。你是对的,因为我的类的用户不会被允许改变我给他的数据结构,为什么我应该给整个数据结构......只需使用一组访问器来公开这个结构的元素缓解他的生活。 – pinpinokio

0

std::vector<T*>std::vector<const T*>不是相同的类型。你怎么能这样写:

std::vector<T*> obj(100); 
std::vector<const T*> & ref = obj; //error 

这就是你在做你的代码,这是无效的。您可以创建一个类型的引用,以引用其他类型的对象。

那么试试这个:

std::vector<const someObj*> getInfoVector() const 
{ 
    return std::vector<const someObj*>(_myVector.begin(), _myVector.end()); 
} 

现在,它返回它包含指针从原来的向量临时载体。此外,请注意,退货类型为而不是参考了。

+0

只是好奇,但为什么'返回值的const'? (还要注意,返回一个副本不像返回一个对真实事物的引用一样的语义。) –

+0

@James:是的。这不是必需的。 – Nawaz

+0

返回值中的指针上的const是,所以没有人可以改变这些指针指向的对象的值。感谢Nawaz,你所说的解释了这种情况,但是如果我返回一个矢量副本,它会使程序变得太慢,所以我买不起(速度对我的应用程序至关重要)。 – pinpinokio

0

你可以写getInfoVector这样的:

std::vector<const someObj*> getInfoVector() const 
{ 
    std::vector<const someObj*> obj; 
    std::copy(_myVector.begin(), _myVector.end(), std::back_inserter(obj)); 
    return obj; 
} 
+0

是的,这是行得通的,但同样会对性能产生严重影响......我不想给我的矢量用户提供特殊的新结构,我只是想保护他免于做愚蠢的事情。 – pinpinokio

0

What would you do in this situation?

作为替代其他的答案,这里是一个简单的方法,它不需要复制或分配:

const someObj* SomeInfo::getSomeObjAt(const size_t& idx) const { 
    return this->_myVector.at(idx); 
} 

甚至更​​好许多情况下,只是SomeInfo 而不是公开它的内部。

+0

谢谢,贾斯汀,这看起来很不错,第一个答案 - >“不要给你的数据结构访问,只有它的元素” – pinpinokio

+0

大概,你指的是史蒂夫杰索普的答案作为第一个答案:我的答案已发布2 (他的回答完全是对我的第一点的更详细的描述)。我的第二点也非常重要。更详细地说,这意味着'SomeInfo'通常应该是对其'somObj'进行操作的,而不是将它们提供给客户端。 – justin