是否会释放阵列,如果是,那么解决方法是什么?
double * GetArrayFromVector( std::map<std::string, double> m, char ** names, int count )
{
if(!names) return 0;
std::vector<double> vec(m.size());
for (int i=0; i<count; ++i)
{
if(!names[i]) return 0;
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec.push_back(iter->second);
else
return 0;
}
return &vec[0];
}
非常感谢
答案 0 :(得分:7)
是的 - 一旦你从函数返回它就会被解除分配,因为在堆栈中声明了vec
。 std::vector
析构函数负责释放内存。因为你正在返回一个解除分配的数组的地址,你将开始搞乱释放内存,这是一个很大的禁忌。充其量,你会立即崩溃。在最糟糕的情况下,你会在一个巨大的安全漏洞中默默地成功。
有两种方法可以解决这个问题:(1)返回整个向量by-value,它生成整个向量的副本,或者(2)通过引用参数返回向量。
解决方案1:
std::vector<double> GetArrayFromVector(...)
{
...
return vec; // make copy of entire vec, probably not a good idea
}
解决方案2:
void GetArrayFromVector(..., std::vector<double> & vec)
{
// compute result, store it in vec
}
答案 1 :(得分:7)
将你的功能分成两部分。
让你的功能只做一个动作:
1.从地图填充矢量。
2.从矢量创建数组
不要忘记通过const引用传递map。
主要注意事项:GetArrayFromVector的调用者负责内存释放。
void FillVector( const std::map<std::string, double>& m,
std::vector< double >& v,
char ** names,
int count )
{
.......
}
double* createArray( const std::vector< double >& v )
{
double* result = new double [v.size()];
memcpy( result, &v.front(), v.size() * sizeof( double ) );
return result;
}
// and finally your function
double* GetArrayFromVector( const std::map<std::string, double>& m,
char ** names,
int count )
{
std::vector< double > v;
FillVector( m, v, names, count );
return CreateArray( v );
}
答案 2 :(得分:4)
是的,数组将被解除分配。
将功能更改为:
double * GetArrayFromVector( std::map<std::string, double> m, vector<double> &vec, char ** names, int count )
{
vec.clear();
vec.reserve(m.size());
for (int i=0; i<count; ++i)
{
if(!names[i]) return 0;
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec.push_back(iter->second);
else
return 0;
}
return &vec[0];
}
或者使用boost::shared_array
(另请参阅boost::scoped_array
)
boost::shared_array<double> GetArrayFromVector( std::map<std::string, double> m, char ** names, int count )
{
boost::shared_array<double> vec(new double[m.size()]);
for (int i=0; i<count; ++i)
{
if(!names[i]) return boost::shared_array<double>();
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec[i] = iter->second;
else
return boost::shared_array<double>();
}
return vec;
}
答案 3 :(得分:2)
vec
是一个局部变量。其范围仅限于GetArrayFromVector()
函数。永远不要返回局部变量的地址。按值返回数组:
std::vector<double> GetArrayFromVector( std::map<std::string, double> m,
char ** names, int count )
或者将对向量的引用作为输出参数传递:
void GetArrayFromVector( std::map<std::string, double> m,
char ** names, int count,
std::vector<double>& vec)
或传递输出迭代器:
void GetArrayFromVector( std::map<std::string, double> m,
char ** names, int count,
std::vector<double>::iterator vecIter)
最后两个需要仔细执行函数定义并调用。
此外,如果你是冒险的游戏,试试这个:
// you'd need to change the value to use when an element is not
// found in the map to something that suits your needs
double pred(std::map<char*, double> haystick, char* const needle) {
std::map<char*, double>::iterator i = haystick.find(needle);
return i != haystick.end() ? i->second : 0;
}
int main(int argc, char* argv[])
{
std::map<char *, double> m;
std::vector<char *> names;
std::vector<double> dv;
m[ "Sasha" ] = 729.0;
m[ "josh" ] = 8154.0;
names.push_back("Sasha");
names.push_back("JonSkeet");
names.push_back("josh");
// transform is part of STL's <algorithm> header
// it takes a container (actually a range -- [begin(), end())
// note it is a half-open range -----------^
// as is customary for all STL algorithms, applies the function
// or functor specified as the last parameter to each element of
// the sequence and writes the result back to another container
// specified via the output iterator -- the third argument
//
// since I have not reserved enough elements for the vector dv
// i cannot blindly use it -- i need a back_inserter to coax
// transform to push_back() instead of do an insert operation
// of course, for vectors, this is costly since reallocations
// may happen, but let's leave the performance aside for a while!
//
// ok, so what about the last parameter, you ask? it has to be an
// unary_operation. well, mostly so. but what is it that we want?
// we want to take an iterator from the original char* (string)
// array and see if there's an entry in the map. if there is one
// we retrieve the associated double value and put it in dv; else,
// we set a default value of 0 -- change it to whatever pleases you
// maybe a std::numeric_limit<double> if it works for you.
//
// you can create a functor inheriting std::unary_function and pass
// it on. that's the easy way out. but what if you already have a
// comparator, a C-style find() function? will it work? yes, it will.
// but we have to wrap it using the function adaptor std::ptr_fun
// to make the compiler happy (after all it wants a unary_function, right?)
//
// this simple scheme of things works very well, save for a last little
// glitch. the comparator actually takes two parameters -- a what to search
// and a where to search. and guess what -- the where to search is always
// fixed. so that gives us a good oppertunity to fix the first parameter to
// our map<char*, double> which is exactly what std::bind1st() does.
// surprisingly, now that you've fixed one function, you no longer have a
// binary function (one taking two arguments) but an unary one -- which is
// just what you'd pass to transform. voila!
std::transform(names.begin(), names.end(), std::back_inserter(dv),
std::bind1st(std::ptr_fun(pred), m));
std::copy(dv.begin(), dv.end(),
std::ostream_iterator<double>(std::cout, "\n"));
return 0;
}
一些有趣的链接:
transform
[实际上,有两种风格] bind1st
或binder1st
[还有一个binder2nd
!] back_inserter
ptr_fun
[查看mem_fun
也是] unary_function
[还有binary_function
] 另请查看Boost。他们用bind()
做了一些魔术!
答案 4 :(得分:0)
您可以通过引用或新建/删除它来传递它,但是在发布后,您的矢量将在函数返回后被破坏。
答案 5 :(得分:0)
是的,当函数结束时,向量(及它保存的数据存储)将被释放。
为什么要创建矢量?如果你想要一个数组,只需创建&amp;填写其中一个..
double * GetArrayFromVector( std::map<std::string, double> m, char * names[], int count )
{
if(!names) return 0;
double* vec = new double[m.size()];
int j = 0;
for (int i=0; i<count; ++i)
{
if(!names[i]) return 0;
std::map<std::string, double>::iterator iter=m.find(name[i]);
if(iter!=m.end())
vec[j++] =iter->second;
else
return 0;
}
return vec;
}
答案 6 :(得分:0)
是的,当函数退出时,向量将被释放(并且'vec'变量超出范围)。因此,您返回的指针将无效。
另一种方法是在堆上分配数组(使用'new'运算符)并返回该指针,但是调用者有责任'删除'指针,这通常是皱眉。
更好的选择是将shared_ptr返回到您的数组。
答案 7 :(得分:0)
由于您事先知道count
,因此使用stl向量没有任何好处。你可以这样做:
double* GetArrayFromVector(std::map<char*, double> m, char** names, int count)
{
double* result = new double[count];
for (int i = 0; i < count; ++i)
{
if(!names[i])
{
delete[] result;
return 0;
}
map<std::string, double>::iterator iter = m.find(name[i]);
if(iter != m.end())
{
result[i] = iter->second;
}
else
{
delete[] result;
return 0;
}
}
return result;
}
请注意,您正在将已分配数组的所有权传递给调用者。就个人而言,我试图以观察RAII principle的方式编写代码;传入要填充的向量,或使用托管/共享指针等(这些选项都已在其他答案中提出)。
答案 8 :(得分:0)
有一个概念调用move constructors,它允许您将(基于堆栈的)对象所拥有的资源的所有权转移到新对象。我听说STLport有一个move_source模板来完成这个
这将来C++0x。
在这种情况下,您将返回std::vector<double>
而不是double*
。
答案 9 :(得分:0)
你可以使用std :: auto_ptr智能指针(但是向你的函数传递矢量引用是更好的解决方案)。
std :: auto_ptr的例子:
std::auto_ptr< std::vector<int> > getArray(int& count){
std::auto_ptr< std::vector<int> > vec(new std::vector<int>());
vec->push_back(10);
vec->push_back(12);
vec->push_back(14);
vec->push_back(16);
count = vec->size();
return vec;
}
int main(){
int size = 0;
std::auto_ptr< std::vector<int> > autoPtrVec = getArray(size);
int* ptr = &(*autoPtrVec)[0];
std::cout << "Size: " << size << std::endl;
for(int i=0; i<size; i++){
std::cout << "[" << i << "]=" << ptr[i] << std::endl;
}
return 0;
}
答案 10 :(得分:0)
有点惊讶没有人提到vector::swap。让调用者传入对向量的引用,该向量的内容将被函数替换:
void GetArrayFromVector( std::vector<double>& output, ... )
{
std::vector<double> vec(m.size());
// construct vec here...
output.swap(vec);
}
顺便说一句:“GetArrayFromVector”并传入地图?
答案 11 :(得分:0)
C ++向量具有data()
method,它返回指向底层数组的指针。
// vector::data
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (5);
int* p = myvector.data();
*p = 10;
++p;
*p = 20;
p[2] = 100;
std::cout << "myvector contains:";
for (unsigned i=0; i<myvector.size(); ++i)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
输出
myvector contains: 10 20 0 100 0