是否可以在 O(1) 时间内为 C++ 向量分配新值?

Posted

技术标签:

【中文标题】是否可以在 O(1) 时间内为 C++ 向量分配新值?【英文标题】:Is it possible to assign new value to C++ vector in O(1) time? 【发布时间】:2016-04-14 06:54:14 【问题描述】:

考虑以下 Python 程序,其步骤如下:

1) 两个列表 A 和 B 被初始化。

2) 我们分配 A = B。这个操作的时间复杂度是 O(1)。

3) 我们为 B 分配了一个不会改变 A 的新列表。

A = [1, 2, 3]
B = [7, 8]
# A contains [1, 2, 3]
# B contains [7, 8]

#------------------------------------

A = B
# A contains [7, 8]
# B contains [7, 8]
# time complexity: O(1)

#------------------------------------

B = [55, 66, 77, 88]
# A still contains [7, 8]
# B now contains [55, 66, 77, 88]

现在,我想在 C++ 中做类似的事情,其中​​ A 和 B 是向量:

1) 两个向量 A 和 B 被初始化。

2) 我们分配A = B。根据en.cppreference.com,这个操作的时间复杂度是O(n)。

3) 我们为 B 分配了一个不会改变 A 的新列表。

vector<int> A = 1, 2, 3;
vector<int> B = 7, 8;
// A contains [1, 2, 3]
// B contains [7, 8]


A = B;   
// A contains [7, 8]
// B contains [7, 8]
// time complexity: O(n)


B = 55, 66, 77, 88;
// A still contains [7, 8]
// B now contains [55, 66, 77, 88]

我的问题

Python 和 C++ 程序之间的区别在于步骤 2) 的时间复杂度,我们在其中分配 A = B。

在 Python 中,它需要 O(1) 时间,因为我们只更改了一个引用。 A 然后“指向”B,即 A 和 B 都是对同一个对象的引用。 在 C++ 中,它需要 O(n) 时间,因为 B 的内容被复制到 A。A 并不“指向”与 B 相同的对象。

有没有办法让 C++ 中的向量 A 在 O(1) 时间内指向向量 B?

注意:我对 C++ 不是很熟悉,所以我什至不知道在 C++ 中将 A 和 B 视为对向量对象的引用是否有效。

【问题讨论】:

Python 变量基本上是指针。也许你也想在 C++ 中创建 AB 指针? 虽然 C++ 有引用,但它们不能以相同的方式使用,因为 C++ 中的引用不能“重新分配”。初始化后,引用将始终引用它最初初始化的内容。更改“引用”的唯一解决方案是使用指针,但是在做一些简单的事情(例如索引向量)时,您必须使用指针取消引用。所以简而言之,不,C++ 没有办法做任何类似于 Python 的事情。 您可以使用指针和动态分配的内存。然后,您只需确保在将 A 指向 B 之前将其删除。 还有另一种解决方案,那就是使用std::vector 的包装类,它在内部使用指向向量的指针。这需要你重新实现std::vector 接口,但是对于大多数函数来说,它只是一个简单的内联函数,它调用容器向量对应的函数。 Python 习语不一定能很好地转换为 C++。如果您正在编写 C++ 代码,请用 C++ 编写,也就是“在罗马时,像罗马人那样做”。 【参考方案1】:

由于在将 B 分配给 A 之后不使用值(之后直接分配给它),因此您可以利用 C++11 移动语义:

vector<int> A = 1, 2, 3;
vector<int> B = 7, 8;
A = std::move(B);
// O(1), see below
// B is in indeterminate but usable state now (probably empty).

B = 55, 66, 77, 88;
// A still contains [7, 8]
// B now contains [55, 66, 77, 88]

移动赋值运算符的时间复杂度为:

除非std::allocator_traits&lt;allocator_type&gt;::propagate_on_container_move_assignment(),否则为常量 是 false 并且分配器比较不相等(在这种情况下 线性)。

source.

【讨论】:

感谢您的建议@el.pescado。使用std::move() 对我有用,尽管我不得不承认我无法理解它需要恒定的时间,因为我不熟悉分配器。 使用std::swap 更明确

以上是关于是否可以在 O(1) 时间内为 C++ 向量分配新值?的主要内容,如果未能解决你的问题,请参考以下文章

C++简单实现vector

对象向量是不是在 C++ 中的堆或堆栈上分配?

将本地 std::vector 分配给 C++ 中的引用

动态分配 SIMD 向量数组是不是安全?

您可以在 C++ 中动态分配带有向量作为字段的类吗?

如何动态分配全局 int*?