当查看 STL 容器的成员函数时,我想到了一个奇怪的想法。为什么没有像这样的功能std::vector<T>::push_back(T)
没有(可选)返回值(迭代器甚至对附加对象的引用)?我知道std::string
功能类似于insert
and erase
返回迭代器,但这是出于显而易见的原因。我认为它通常会保存这些函数调用之后的第二行代码。
我相信C++的设计者有一个很好的理由,请赐教:)
UPDATE:我在这里包含一个真实的代码示例,它可以减少代码长度:
if( m_token != "{" )
{
m_targets.push_back( unique_ptr<Target>(new Dough(m_token)) );
return new InnerState( *(m_targets.back()), this );
}
可以减少到
if( m_token != "{" )
return new InnerState( *(m_targets.push_back( unique_ptr<Target>(new Dough(m_token)) )), this );
如果我假设std::list::push_back
返回对添加元素的引用。代码有点重,但这主要是(两组括号)由于unique_ptr
的构造函数并取消引用它。也许为了清楚起见,没有任何指针的版本:
if( m_token != "{" )
{
m_targets.push_back( Dough(m_token) );
return new InnerState( m_targets.back(), this );
}
vs.
if( m_token != "{" )
return new InnerState( m_targets.push_back( Dough(m_token) ), this );
不可能以安全的方式返回添加的元素或容器成员函数中的容器。 STL容器主要提供“强有力的保障”。返回被操作的元素或容器将无法提供强保证(它只会提供“基本保证”)。
其背后的原因是,返回某些内容可能会调用复制构造函数,这可能会引发异常。但是该函数已经退出,因此它成功地完成了其主要任务,但仍然抛出异常,这违反了强保证。您可能会想:“那么让我们通过引用返回!”,虽然这听起来像是一个很好的解决方案,但它也不是完全安全的。考虑以下示例:
MyClass bar = myvector.push_back(functionReturningMyClass()); // imagine push_back returns MyClass&
尽管如此,如果复制赋值运算符抛出异常,我们不知道push_back是否成功,从而间接违反了强保证。尽管这并不是直接违规。当然使用MyClass& bar = //...
相反,会解决这个问题,但这会很不方便,容器可能会进入不确定状态,只是因为有人忘记了&
.
一个很相似的推理背后的事实是std::stack::pop()
不返回弹出的值。反而top()
以安全的方式返回最高值。调用 top 后,即使复制构造函数或复制赋值构造函数抛出异常,您仍然知道堆栈没有更改。
EDIT:我相信,如果迭代器类型的复制构造函数提供不抛出保证(我所知道的每个人都这样做),则为新添加的元素返回迭代器应该是完全安全的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)