【问题标题】:Const-Correctness for Elements of std Containers标准容器元素的常量正确性
【发布时间】:2012-11-18 17:17:25
【问题描述】:

以下是不好的:

vector<const int> vec;

问题是模板类型需要是可分配的。以下代码编译 [EDIT: in Visual Studio 2010],证明了上述问题:

vector<const int> vec;
vec.push_back(6);
vec[0] += 4;

对于更复杂的类型,这可能是一个严重的问题。

我的第一个问题是这种行为是否有原因。在我看来,有可能制作不允许上述内容的 const 容器和允许它的非 const 容器。

其次,有没有办法让容器以这种方式发挥作用?

第三,这里实际发生了什么(使用用户类型)?我意识到这是未定义的行为,但 STL 是如何编译它的呢?

【问题讨论】:

  • 您正在以一种未定义的行为方式使用标准库。这意味着对于应该发生的事情根本没有要求。某些操作可能看起来有效,而其他操作可能无效。并且在不同的实现之间没有预期的一致性。
  • 这不能在 g++ 4.6.3 上编译。
  • 你的代码不能用 c++ 标准编译。
  • Visual Studio 2010 编译它。嗯。
  • 我的猜测是,正确定义它应该如何为标准工作是不值得的,因为你并不经常需要这样的行为。

标签: c++ std


【解决方案1】:

不允许std::vector&lt;T const&gt; 的原因是向量中的对象在插入到与开头不同的位置时可能需要重新洗牌。现在,成员 std::vector&lt;T&gt;::push_back(T const&amp; v) 在概念上等同于(将分配器模板参数排除在外,因为它与本次讨论无关)

template <typename T>
void std::vector<T>::push_back(T const& v) {
    this->insert(this->end(), v);
}

这似乎是它在某些实现上的实现方式。现在,这个操作通常需要一些对象可能需要移动,因此,T 参数需要是可分配的。似乎 MSVC++ 附带的标准库并未委托操作,而是执行所有必要的处理,即在空间不足时调整数组大小并适当移动对象,在push_back() 中。尚不清楚对 T 类型有什么要求才能使用 push_back()

原则上,在中间支持T constinsert() 操作的容器是可能的,但是:没有什么要求内部存储是T 而不是typename std::remove_const&lt;T&gt;::type,同时暴露T&amp;界面。有必要注意const 版本的操作,如operator[](),因为当T 是某个类型S const 时,仅使用T const&amp; 作为返回类型将导致类型S const const。在 C++ 2003 中,这将是一个错误,在 C++ 2011 中,我认为 const 刚刚折叠。为了安全起见,您可以使用typename std::add_const&lt;T&gt;::type&amp;

【讨论】:

    猜你喜欢
    • 2014-01-03
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多