如何将vector<int>转换为int*?

4

我需要维护一个从2004年以来没有人碰过的程序。

class CSolver
{  
 ...  
 ClauseIdx add_clause (int * lits, int n_lits);
}

void and2 (CSolver & solver)   
{  
vector <int> lits;  
...  
solver.add_clause(lits.begin(), lits.size());  
}

编译器报错:

错误: 无法调用‘CSolver::add_clause(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, size_t)’函数

我尝试进行转换。
solver.add_clause((int*)lits.begin(), lits.size());

但是还有一个问题:

错误:从类型“__gnu_cxx::__normal_iterator<int*,std::vector<int,std::allocator<int> > >”无效地转换到类型“int*”

我希望能够快速解决这个问题,因为改变CSolver的接口会导致整个程序的改变。

提前感谢您的帮助。


1
看起来你的旧编译器使用了一个简单指针作为迭代器。这种做法已经不常见了。 - Mark Ransom
也许考虑重构一下。 - g24l
5个回答

11
像这样:

solver.add_clause(lits.data(), lits.size());

不要在不理解其含义的情况下添加强制转换。

该函数需要一个 int 类型的数组,它通过指针和大小请求它们。这是一个常见的 C 习惯惯例。

幸运的是,std::vector 正好存储为连续的数组,因此我们可以获取到第一个元素的指针 (lits.data(), &lits[0], &lits.front() 等),然后只需传递大小即可。


7

4

这应该可以在不支持C++11的多个平台上运行:

solver.add_clause(&lits[0], lits.size());

编辑:这里的假设是您只想满足API,并且已经调整了向量大小以分配足够的int进行操作,并且add_clause方法不会干扰指针,分配新的整数或以其他方式违反堆。

这种解决方法之所以可行,是因为向量在堆上具有内部连续分配,因此对第一个元素的指针就足以将容器用作数组,以便进行c风格的元素迭代,只要注意元素的数量即可。


我认为data(来自其他答案)在C++11之前就已经存在了,它是否发生了变化? - Mark Ransom
是的,但它并不在所有STL的实现中都可用,这对需要支持多个平台编译的开发人员来说是一个问题。C++11标准化了这种方法,现在的问题是你是否需要支持可能没有它的旧编译器? - AJG85

2
您可以像这样使用,以避免强制转换:
solver.add_clause(&(*lits.begin()), lits.size())

在这里,取出*list.begin()并获取其地址,该地址是一个int *


0

别急,亲。当然你可以应用其他人已经提出的解决方案:

solver.add_clause(lits.data(), lits.size());

或者我的首选:

solver.add_clause(&lits[0], lits.size());

这表示这里发生了一些不寻常的事情,

但您首先应该考虑,即使标准定义向量内部存储应连续, 这并不意味着它不可重新分配。不幸的是,后者经常发生。


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