哪个向量地址更安全?

4
假设一个函数需要一个指向类型为T的向量的指针,但是当我只有一个类型为T的向量的向量(类型不保证是POD)时,这样做是否可行?
std::vector<std::vector<T>> input;
auto selectedVectorPtr=&input[j];

比这更安全

std::vector<std::vector<T>> input;
auto selectedVectorPtr=&(input[j]);

同时假设输入的范围直到以selectedVectorPtr作为参数的函数结束。

我的顾虑(/误解)是:

  • 是否会创建任何临时对象?因此,取其地址是否有问题?
  • 对T类型的&或[]运算符重载是否会影响操作符优先级的更改?
  • 如果在获取地址后重新调整了vector(或两者都是),会怎样?

运算符优先级有规则。这与安全无关,但与正确性有关。 - 463035818_is_not_a_number
第二个选项在某种意义上更“安全”,因为如果你匆忙时,不会误解它为(&input)[j]。否则,它们是等效的。 - molbdnilo
在函数中使用指针必须像 (*parameter)[k] 这样,但它看起来当然不同,我也担心 *parameter[k] - huseyin tugrul buyukisik
3个回答

10

operator[]的优先级高于operator&(后缀运算符的优先级最高),因此它在此处首先被计算,不需要括号。在这里&input[j]&(input[j])之间没有区别。


替代更简单的语法:

auto selectedVectorPtr = input.data() + j;

这里也不需要使用 std::addressof


() 会创建一个临时对象还是直接解引用数组呢? - huseyin tugrul buyukisik
1
@cmaster 我更喜欢使用“指针 + 索引”。但是感谢你分享你的思考过程。 - Maxim Egorushkin
你为什么更喜欢使用“指针+索引”?你的思维过程是什么? - cmaster - reinstate monica
啊,那么pointer + index这种写法确实是一个很好的理由。我不确定C标准是否允许&*产生未定义行为。我一直以为编译器会自动优化这两个操作(在C中,&*总是无效的),因为当CPU获取地址时,它从来没有触碰指针后面的对象。也许我太粗心了... - cmaster - reinstate monica
除此之外,从概念上讲,&pointer[index] 是两个操作(可能会重载 operator&),而 pointer + index 只是一个操作。这就是为什么我更喜欢后者。 - Maxim Egorushkin
显示剩余4条评论

8

运算符优先级决定了[]会在前置的&之前被计算。因此,这两个表达式没有区别。

如果你正在考虑代码片段的安全性问题,需要考虑&input[j]的两个问题(不考虑外部括号):

  • 索引可能越界,导致未定义的行为。您可能希望使用(可能会抛出异常但更安全的)std::vector::at而不是std::vector::operator[],并将其包装在try-catch块中。
  • 如果要获取先前未知的T的地址,则可以为T重载operator &。虽然这本质上是邪恶的,但您可以使用std::addressof来减轻可能性。请注意,在您的情况下,这是不必要的,因为您正在获取std::vector实例的地址。

你的意思是如果有人使用类而不是float或double,它会导致操作优先级的改变,因此运算符&将具有第一优先级吗? - huseyin tugrul buyukisik
1
不,你不能通过重载更改运算符优先级。但是你可以通过为用户定义的类型重载operator &来更改其含义。 - lubgr
1
在我看来,过载 operator & 的人得到了他们应得的... 所以,没有必要使用 std::address_of<> ;-) 很好地提到了这些问题,加一分! - cmaster - reinstate monica

0

&input[j]&(input[j])没有任何区别。这是因为operator[]operator&的优先级高。

因此,在这两种情况下,它都将评估为&(input[j])


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