这些天我正在学习STL,我想知道STL容器是否通过引用返回?
e.g:
vector.first();
map[key];
*vector.begin();
Or any possible return that ends with element (or value type) of container
e.g:
std::vector<int> elements;
elements.push_back(20);
elements[0]=60; // this will also change the value
elements.front() = 23; // even the functions also behave same way like subscript operator
这是所有容器的情况吗?还是有一些要考虑的问题我没有表现出来?
答案 0 :(得分:13)
无法以安全的方式返回添加的元素或容器成员函数中的容器。 STL容器主要提供“强保证”。返回操纵元素或容器将使得不可能提供强有力的保证(它只提供“基本保证”)。这些术语的解释在boost的网站 Exception-Safety in Generic Components 上提供。请参阅下面的Boost's website。
回到主题:根据这个previous SO answer,背后的原因是,返回一些东西可能会调用一个拷贝构造函数,这可能会引发一个异常。但是这个功能已经退出,所以它成功地完成了它的主要任务,但仍然抛出异常,这违反了强有力的保证。您可能会想:“那么让我们通过引用返回!”,虽然这听起来像是一个很好的解决方案,但它也不是非常安全。请考虑以下示例:
MyClass bar = myvector.push_back(functionReturningMyClass()); // imagine push_back returns MyClass&
但是,如果复制赋值运算符抛出,我们不知道push_back是否成功,从而间接违反了强保证。即使这不是直接违规。当然使用MyClass& bar = //...
可以解决这个问题,但是容器可能会进入不确定的状态会非常不方便,因为有人忘记了&amp;。
std::stack::pop()
未返回弹出值的事实背后有一个非常相似的推理。相反,top(
)以安全的方式返回最顶层的值。在调用top之后,即使复制构造函数或复制赋值构造函数抛出,您仍然知道堆栈没有改变。
答案 1 :(得分:2)
容器的所有类型(序列,关联)旨在提供一致的接口(如果可能)。它使学习它们相对容易,并且使用它们更容易(只要你已经正确地学习它们了!;))。
因此,例如,所有容器的operator[]
将返回对索引实体的引用(在关联容器的情况下,将首先创建它)。对于序列容器,这提出了一个关于边界检查的有趣观点 - 但这是一个不同的故事。同样,如果您采取任何其他常见操作(insert
等)将具有类似的界面。您最喜欢的参考文献通常会提供您需要的所有信息。
答案 2 :(得分:2)
是的,stl容器的重载[]
运算符返回一个引用。因此,在上面的示例中,m
和elements
中的值将被更改。
来自http://www.cplusplus.com/reference/stl/vector/operator%5B%5D/:
vector的定义或运算符[]是:
reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;
其中'成员类型reference
和const_reference
是向量容器元素的引用类型(在大多数存储分配模型中通常分别定义为T&
和const T&
)'
编辑:请注意,并非所有stl容器都有重载的[]
运算符。那些不是:list
,multimap
,multiset
,priority_queue
,queue
,set
和stack
。
答案 3 :(得分:1)
std::vector<bool>
返回其他内容(假设您的意思是标准库,而不是SGI STL)。但它通常也被认为是一个不值得被称为容器的错误。