【问题标题】:how to pass a stl vector to a function which takes a const [] (c++)如何将 stl 向量传递给采用 const [] (c++) 的函数
【发布时间】:2009-08-25 16:31:17
【问题描述】:

我有一个 3d stl 矢量,

vector<vector<vector<double> > > mdata;

我还有一个功能

myfun(const double ya[]);

更准确地说,它是来自 GNU 科学图书馆的一个函数,

gsl_spline_init(gsl_spline * spline, const double xa[], const double ya[], size_t size);

但这与我的问题无关。

所以现在我想将数据的“最后一个”维度传递给 myfun。我一直在尝试这个:

for (int s = 0; s < msize; s++) {
    accelerators = new gsl_interp_accel*[msize];
    splines = new gsl_spline*[msize];
    for (int i = 0; i < msize; i++) {
        accelerators[i] = gsl_interp_accel_alloc();
        splines[i] = gsl_spline_alloc(gsl_interp_cspline_periodic, msize+1);
        gsl_spline_init(splines[i], &(*mgrid.begin()), &(*mdata[s][i].begin()), msize+1);
    }
}

但是编译器(g++、64bit、Ubuntu)抱怨:

在成员函数中 ‘std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > > SimpleAmfCalculator::interp_m(int)’: Calculator.cpp:100:错误:不能 将“std::vector<double, std::allocator<double> >*”转换为“const double*”,将参数“3”转换为“int gsl_spline_init(gsl_spline*, const double*, const double*, size_t)”使: *** [Calculator.o] 错误 1

非常感谢任何帮助!

【问题讨论】:

  • 您显示了“数据”的声明,但出现错误的行中的变量是“mdata”。他们应该是一样的吗?

标签: c++ function vector constants


【解决方案1】:

你可以传递第一个元素的地址,例如:

#include <vector>

void fun(const double data[])
{

}

int main()
{
    std::vector<std::vector<std::vector<double> > > data3d;
    ....
    fun(&data3d[0][0][0]);
}

vector 的元素是连续存储的。所以我希望这种方式是标准的:)

23.2.4 Class template vector

1 向量是一种 支持随机访问的序列 迭代器。此外,它支持 (摊销)恒定时间插入和 最后擦除操作;插入 并在中间擦除取线性 时间。存储管理处理 自动,虽然提示可以 给予提高效率。这 elements of a vector are stored 连续,表示如果v 是 向量,其中 T 是一些 类型不是 bool,那么它服从 身份:

&v[n] == &v[0] + n for
all 0 <= n < v.size().

【讨论】:

  • 我想我曾经读过这曾经在实践中或“事实上”工作(它假设向量是使用连续数组在内部实现的),并且在标准的较新版本中现在可以在理论或“法理”。
  • 我不确定这是否是可移植的(vector 不提供像 std::string 这样的 .data() 方法),但这可能适用于大多数编译器。
  • 只要至少有一个元素,它就可以工作。还要注意,您可能只能访问data3d[0][0][0].size() 元素,因为其他“子数组”(实际上是向量)没有分配在它旁边(这似乎很明显,但我想很容易被忽略)。
  • 如果向量中的一个恰好是空的,这将失败。
  • 好吧,这对我不起作用——至少当我这样做时:gsl_spline_init(splines[i], &mgrid[0], &mdata[s][i][0], msize+1)
【解决方案2】:

这需要一个通用的解决方案。

template<typename T, typename A>
T* PointerOf(std::vector<T,A> & vec)
{
    return &vec.at(0);
}

template<typename T, typename A>
const T* ConstPointerOf(const std::vector<T,A> & vec)
{
    return &vec.at(0);
}

myfun(ConstPointerOf(mdata[s][i]));

编辑: 我按照 cmets 中的建议为向量分配器添加了模板参数;我还使用了 at() 而不是 [],因此我不必检查空向量,并且我为 const 指针添加了该函数的第二个版本。

【讨论】:

  • 这个不是还要给分配器提供模板吗?
  • @GMan,如所写,它将仅接受具有 std::allocator&lt;T&gt; 分配器的向量。我想这对大多数人来说都很好。但肯定添加分配器会更通用:)
  • 你说得对,我从来没有在我的向量中使用过分配器,所以我没有想到。修复它只是添加第二个模板参数的问题吗?
  • 为什么const 版本的命名不同? (哦,看看stackoverflow.com/questions/1339470/…
  • 我命名了 const 版本,因此您可以选择返回 const 或非 const 指针。由于 T* 将隐式转换为 const T*,我可能不需要这样做。不过仍然需要两个版本的函数。
【解决方案3】:

我认为

&(*mdata[s][i].begin());

正在返回 std:vector 类型的 double

【讨论】:

  • 不,它返回一个迭代器。你在考虑front()。
  • 不,front 返回一个 double。但它确实返回了一个迭代器。没有函数调用会返回 double 类型的 std::vector。
  • "Calculator.cpp:100: 错误:无法将参数 '3' 的 'std::vector >*' 转换为 'const double*' "
  • 返回一个迭代器,它可能与 double* 兼容,也可能不兼容。
【解决方案4】:

所以,以下似乎对我有用:

#include <vector>

void fun(const double data[])
{

}

int main()
{
    std::vector<std::vector<std::vector<double> > > data3d;
    ....
    fun(&(data3d[0][0].front()));
}

【讨论】:

    猜你喜欢
    • 2013-12-19
    • 2020-09-28
    • 2017-08-12
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多