STL向量中foo[i]和foo->at(i)的区别

3

为什么

foo = (bar->at(x))->at(y);

可以运行,但是

foo = bar[x][y];

无法运行,其中bar是一个向量的向量(使用c++ stl)

声明如下:

std::vector< std::vector < Object * > * >

注:Object为一个对象类型。

8
std::vector<std::vector *> 这个向量是怎么声明的?你使用 at 表示使用指针,或者这是一个打字错误吗?否则,应该写成 bar.at(x).at(y) 才对。 - Skurmedel
8
仅仅因为C++有指针并不意味着你程序中的每一个变量都必须是指针。将所有指针都移除,程序应该就可以正常工作了。 - jalf
2
看起来bar是一个指向包含指针的容器的指针。但是知道'bar'的实际类型会更好。 - Martin York
就像我和其他人在下面所说的那样,您不能在未对指针进行解引用的情况下使用 operator[]。(可以使用 bar->operator[]()(*bar)[]。自由函数可能是第二干净的方法。最干净的方法是不使用指针。) - GManNickG
@GMan:当然可以在指针上使用[]。它只是没有做到OP的本意。 ;) - jalf
7个回答

9

它是一个向量的向量还是指向向量的指针的向量?你的代码应该像广告中所说的那样工作:

typedef std::vector<int> vec_int;
typedef std::vector<vec_int> multi_int;

multi_int m(10, vec_int(10));

m.at(2).at(2) = /* ... */;
m[2][1] = /* ... */;

但是你的代码似乎有:
typedef std::vector<vec_int*> multi_int; // pointer!
multi_int* m; // more pointer!

如果您有指针,您需要先进行解引用才能使用 operator[]:
(*(*m)[2])[2] = /* ... */;

那可能会很丑陋。暂时使用引用可能会更好:
multi_int& mr = m;
(*mr[2])[2] = /* ... */;

虽然仍有一些不美观的地方。也许自由函数会有所帮助:

template <typename T>
typename T::value_type& access_ptr(T* pContainer,
                                    unsigned pInner, unsigned pOuter)
{
    return (*(*pContainer)[pInner])[pOuter]);
}

access_ptr(m, 2, 2) = /* ... */
最好的情况是摆脱指针。指针可能会泄漏并出现各种问题,例如在抛出异常时泄漏。如果您必须使用指针,请使用来自boost的pointer container用于内部向量,并将实际对象存储在smart pointer中。
另外,您的标题有些误导。 atoperator[]之间的区别在于at执行范围检查。否则,它们是相同的。

我假设bar是一个std::vector<std::vector<T> >*,因此使用了->at() - jalf
2
它需要是std::vector<std::vector<T>* >*,有两个-> - CB Bailey
哦,是的,我没有看到另一个。查尔斯当然是对的。 - jalf

4

你确定你有一个向量的向量吗?如果是这样的话,那么

foo = bar[x][y];

would be like

foo = bar.at(x).at(y);

但不具备at的范围检查和异常行为。

如果bar->at(x)->at(y)可行,则可能与(*(*bar)[x])[y]有些相似,而不是bar[x][y],但这必须意味着bar不是向量的向量。


1

好的,如果bar是一个指针(正如第一个例子所示),那么你需要重写你的第二个例子:

(*(*foo)[x])[y]

1
如果bar是一个指针,你需要先解引用它:
(*bar)[x][y]

如果它是指向一个指针向量的向量:

(*(*bar)[x])[y]

正如R Samuel Klatchko和其他人所提到的那样


1

看起来你有一个指向指针向量的指针...

所以如果你想尝试这样做,你需要

foo = (*((*bar)[x]))[Y];

使用向量的向量(即std::vector< std::vector< datatype > >)。

编辑:还值得注意的是,at确实进行一些范围检查,因此,只要您不需要这些范围检查,就比使用operator[]慢。


0

对于

foo = (bar->at(x))->at(y);

要让bar工作,它必须是一个指针,并且它所指向的向量必须包含指针。

对于

foo = bar[x][y];

要使其工作,bar 必须是一个包含向量(而不是指针)的 vector


0

取决于你如何定义“工作”和“不工作”。当它“不工作”时会发生什么?

两者之间的主要区别在于at执行边界检查,而operator[]则不执行。

但在你的情况下,问题在于bar不是一个向量的向量。它似乎是指向指针的向量的指针。(这本身就是一个坏迹象。它可能不需要是一个指针。一切也都是用new动态分配的吗?默认情况下不要这样做)

这意味着你试图在指针上调用operator[],而不是一个向量——虽然它被定义了,但它做的事情与你期望的不同。你第二个例子中的代码实际上等价于(*(bar+x))[y]——除了越界导致未定义行为外,结果将是一个指向foo类型的向量的指针,而不是该向量的一个元素。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接