是否可以在 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++ 中创建A
和 B
指针?
虽然 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<allocator_type>::propagate_on_container_move_assignment()
,否则为常量 是false
并且分配器比较不相等(在这种情况下 线性)。
source.
【讨论】:
感谢您的建议@el.pescado。使用std::move()
对我有用,尽管我不得不承认我无法理解它需要恒定的时间,因为我不熟悉分配器。
使用std::swap
更明确以上是关于是否可以在 O(1) 时间内为 C++ 向量分配新值?的主要内容,如果未能解决你的问题,请参考以下文章