c++ - 如何正确(但有效地)实现类似 "vector::insert"的东西? (指针别名)

标签 c++ pointer-aliasing

考虑 vector 的这个假设实现:

template<class T>  // ignore the allocator
struct vector
{
    typedef T* iterator;
    typedef const T* const_iterator;

    template<class It>
    void insert(iterator where, It begin, It end)
    {
        ...
    }

    ...
}

问题

我们在这里面临一个微妙的问题:
beginend 有可能引用同一 vector 中的项目,after where

例如,如果用户说:

vector<int> items;
for (int i = 0; i < 1000; i++)
    items.push_back(i);
items.insert(items.begin(), items.end() - 2, items.end() - 1);

如果 It 不是指针类型,那么我们没问题。
但是我们不知道,所以我们必须检查 [begin, end) 没有引用 vector 中已经存在的范围。

但是我们该怎么做呢?根据 C++,如果它们引用同一个数组,那么指针比较将是未定义的!
因此编译器可能会错误地告诉我们这些项目没有别名,而实际上它们确实有,从而给我们带来不必要的 O(n) 减速。

可能的解决方案和注意事项

一种解决方案是每次 复制整个 vector ,以包含新项,然后丢弃旧拷贝。

但在上面的示例中,我们复制 1000 个项目只是为了插入 1 个项目的场景非常慢,即使我们显然已经有足够的容量。

是否有一种通用的方法可以(正确地)有效地解决这个问题,即在没有混叠的情况下不会受到 O(n) 减速的影响?

最佳答案

您可以使用谓词 std::less 等,它们保证给出总顺序,即使原始指针比较没有。

来自标准[comparisons]/8:

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

关于c++ - 如何正确(但有效地)实现类似 "vector::insert"的东西? (指针别名),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12031781/

相关文章:

c++ - 在 Linux 上使用文件路径字符串,使用什么编码?

c++ - Placement-new 与 gcc 4.4.3 严格别名规则

python - 在 python 中创建列表的一部分的别名

c - 别名 "const restrict"指针参数是否合法?

java - 对象中的别名

c++ - 当我声明一个引用变量时堆栈会发生什么? C++

c++ - 使用 __int64 参数调用 GetSystemTimeAsFileTime

c++ - #include <opencv2/opencv.hpp> 在 VS 2013 中不起作用

c++ - 如何用计算机代码检查无限集是否在加法下是封闭的?

c++ - std::inner_product 计算 vector 的标准差