为啥我们不能在动态向量的情况下使用方括号?

Posted

技术标签:

【中文标题】为啥我们不能在动态向量的情况下使用方括号?【英文标题】:Why can't we use square brackets in case of dynamic vectors?为什么我们不能在动态向量的情况下使用方括号? 【发布时间】:2021-10-01 11:36:19 【问题描述】:
#include <iostream>
using namespace std;
#include <vector>
#include <queue>

int main()
   vector<int> *v = new vector<int>;
    v -> push_back(1);
    
    //min priority queue
    priority_queue<int, vector<int>, greater<int>> pq;

     pq.push(v[0]); //Able to do pq.push(v -> at(0))

那么为什么会出现错误?我不是在我的优先级队列中推送一个整数吗?

【问题讨论】:

v 是(不必要的)一个指针。 v[0] 正在推迟该指针。您正在尝试将 vector&lt;int&gt; 推送到 int 的优先级队列中 不要动态分配向量。向量确实已经动态分配了它的元素,因此(几乎)没有充分的理由使用new std::vector&lt;int&gt;; @Aman pq.push 将只接受一个 int 作为输入。在您的情况下,v[0] 将返回整个向量。如果你真的想使用 [] 运算符,你可以使用 pq.push(v[0][0]) @Aman 没有。 * ( v + 0) == *(v) == *v 这只是取消引用指针,而不是访问向量的元素 @Aman 现在我明白你的困惑了;)。 std::vector 不是数组。 arr[0] == *( arr + 0) == *arr。第一个元素与第一个元素具有相同的地址,因此 dereferencign arr 为您提供第一个元素。 vector 的情况并非如此 【参考方案1】:

标准向量已经动态管理其缓冲区。

在 99.9% 的情况下,new std::vector 是一个错误。

vector<int> v;
v.push_back(1);

//min priority queue
priority_queue<int, vector<int>, greater<int>> pq;

pq.push(v[0]); 

这行得通。

如果您确实在 0.1% 的情况下认为新向量有意义,请将 v[0] 更改为 (*v)[0]

v[0] 所做的是将指针 v 视为指向向量数组的指针。然后它选择第 0 个。它不会选择第 0 个元素的第 0 个元素。 v[0][0] 也可以工作(但当v 实际上不是指向数组的指针时,这样做会很糟糕;通常会让读者感到困惑)。

所以C++从C继承了一个数组指针对偶性。当你有一个指针时,你可以用方括号把它当作一个数组来对待,就好像它是指向数组第一个元素的指针一样。这实际上是数组[] 的工作原理;数组被隐式转换为指针,然后 [] 应用。当您有一个未指向数组的指针时,这会令人困惑。

C++ 也有对象,这些对象可以重载方括号等运算符。重载发生在对象上而不是指向这些对象的指针上。

所以vector[] 伪装成一个数组并找到向​​量所拥有的元素。 ptr_to_vector[] insteat 将其视为从 *ptr_to_vector 开始的向量数组,几乎不是您想要的。

C++ 在拥有可以是值的完整对象方面是相对独特的。很少有语言可以。如果您来自其他语言,这可能会令人困惑。尽可能采用 C++ 中的值语义。

【讨论】:

new std::vector is a mistake. 完全取决于上下文。他的问题是为什么在这种情况下他的编译失败了。 @StoicaMircea 在问题的上下文中,可能在所有其他上下文中的 99.9% 中,这是一个错误。正如答案中已经提到的。它并不完全依赖 @super in 99.99% 是使用向量的错误。如下使用数组:int v[1] = 1;。这是你的答案。当您知道自己在做什么时,没有什么是错误的。【参考方案2】:

这将修复你的编译

pq.push((*v)[0]); 

因为 v 是指向 vector&lt;int&gt; 的指针。

在这种情况下,pq.push 将只接受一个 int 作为输入。 v[0] 将返回一个 vector&lt;int&gt; 对象。如果您真的想使用 [] 索引运算符,可以使用 pq.push(v[0][0])

重做的代码:

#include <iostream>
using namespace std;
#include <vector>
#include <queue>

int main()
    vector<int> *v = new vector<int>;
    v -> push_back(1);
    
    //min priority queue
    priority_queue<int, vector<int>, greater<int>> pq;

    pq.push((*v)[0]);
    delete v; // don't forget.

【讨论】:

它会使编译错误消失,但不是解决问题的好方法 - 请参阅其他答案***.com/a/69405441/151019 要回答我会说错误是您在向量上使用 new - 修复该行 @mmmmmm 再看看我的回答。问题出在哪里??我们不要使用指针,因为它们很复杂,对吧?他将不得不在某个时候处理指针,最好从现在开始学习,而不是花费数小时弄清楚如何修复编译.. 这是一个糟糕的借口,不能说明不好的做法。对于 OP 可以了解它们的指针,将会有大量的合法需求。 newing 标准库容器非常可能不是。我们不要鼓励反模式。 @sweenish 确实对于这个例子来说这是一个不好的做法,但这是另一个话题。发布这个问题的人并没有要求一个好的做法。他问为什么编译失败。

以上是关于为啥我们不能在动态向量的情况下使用方括号?的主要内容,如果未能解决你的问题,请参考以下文章

为啥AngularJS货币过滤器格式负数用括号

为啥会出现这个错误?我们不能在函数括号内使用格式宏吗?

为啥我不能在没有括号的插值字符串中使用条件运算符? [复制]

为啥 C++11 类内初始化程序不能使用括号?

查找并标注匹配的括号对

为啥我们在haskell中编写函数时需要使用括号?