【问题标题】:How to copy the contents of std::vector to c-style static array,safely?如何安全地将 std::vector 的内容复制到 c 样式的静态数组?
【发布时间】:2009-03-11 06:34:25
【问题描述】:

我需要处理涉及中间插入的固定数组中的数据。 而不是使用 memcpy 等。我想使用矢量。我想要的时候有问题 将向量元素复制回 c 样式数组。 代码如下:

void tryvector()
{
    using namespace std;
    const int MAX_SIZE=16;
    BYTE myarr[MAX_SIZE]={0xb0,0x45,0x47,0xba,0x11,0x12, 0x4e};
    vector<BYTE> myvec (myarr, myarr+MAX_SIZE);
    vector<BYTE>::iterator it;

    printf("myarr pre :");
    for(int i=0;i<MAX_SIZE;++i){
        printf("%02x ", myarr[i]) ;   

    }

    printf("\nmyvec pre :")
    for(it=myvec.begin(); it<myvec.end();++it){
       cout<<hex<<static_cast<int>(*it)<<" ";

    }

    it = myvec.begin()+ 3;
    myvec.insert(it,0x5f);
    printf("\nmyvec post:");
    for(it=myvec.begin(); it<myvec.end();++it){
       cout<<hex<<static_cast<int>(*it)<<" ";


    }

    copy(myvec.begin(), myvec.end(), myarr); //???
    printf("\nmyarr post:");
    for(int i=0;i<MAX_SIZE;++i){
        printf("%02x ", myarr[i]) ;   

    }

}

我正在使用 vs 2005。 这是警告:

warning C4996: 'std::_Copy_opt' was declared deprecated
1>        c:\program files\microsoft visual studio 8\vc\include\xutility(2270) : see      declaration of 'std::_Copy_opt'
1>        Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library'
1>        c:\documents and settings\mhd\my documents\tesvector.cpp(50) : see reference to function template instantiation '_OutIt  std::copy<std::_Vector_iterator<_Ty,_Alloc>,BYTE*>(_InIt,_InIt,_OutIt)' being compiled
1>        with
1>        [
1>            _OutIt=BYTE *,
1>            _Ty=BYTE,
1>            _Alloc=std::allocator<BYTE>,
1>            _InIt=std::_Vector_iterator<BYTE,std::allocator<BYTE>>
1>        ]

当我运行它时,我得到了以下运行时错误:


    Run-Time Check Failure #2 - Stack around the variable 'myarr' was corrupted.

请注意,我使用向量而不是列表或双端队列,因为 像上面的代码这样的“中间插入”是一个特殊的问题。 它会比“最后插入”发生得少,并且 '元素的随机访问'。
有什么解决办法吗?

任何类似的答案:“你使用 c++,放弃 c 风格的数组实现。 对所有数组实现只使用向量”并不是很有帮助。

谢谢。

【问题讨论】:

  • 仅仅因为你使用 vector 而不是数组并不意味着 memcpy() 没有发生。 vector 方法比较容易理解,但是做的一样,对于大数组性能会很差。

标签: c++ arrays vector


【解决方案1】:

问题是您正在向向量中添加东西,因此它最终会包含比您初始化它的 myarr 数组中的更多元素。

如果要将向量复制回数组中,则需要缩小它的大小:

myvec.resize( MAX_SIZE);

或者您可以限制复制回来的元素数量:

copy( myvec.begin(), myvec.begin()+MAX_SIZE, myarr);

如果您希望myarr 数组包含所有元素,那么它需要大于MAX_SIZE,并且您已经发现为什么人们建议使用vector 而不是原始数组(vector s 知道如何增长,数组不会)。

请注意,虽然您不想要“任何类似的答案:“您使用 c++,放弃 c 样式数组实现。所有数组实现仅使用向量””,但您通常可以使用 vector并将&amp;myvec[0] 传递给需要原始数组的例程。出于这个原因,vector 需要像原始数组一样连续存储其元素。

由于您收到“不安全操作”警告,因此您使用的是 Microsoft 的编译器。为了安全地解决问题,您应该使用checked_copy 算法而不是copy。作为Evgeny Lazin indicates,您可以为您的数组创建一个检查迭代器以传递给checked_copy 算法。

使复制安全且不需要 Microsoft 扩展的其他选项是将数组包装在一个类(可能是模板化的)中,该类跟踪数组大小并提供以安全方式将数据复制到数组中的方法。 STLSoft's array_proxy templateBoost's boost::array 之类的东西可能会有所帮助。

【讨论】:

  • 这似乎有效,但警告仍然存在。可以吗?
【解决方案2】:

一般来说,我猜你可以这样做:

void *myarr;

if((myarr = malloc(myvec.size() * sizeof myvec[0])) != NULL)
{
  memcpy(myarr, &myvec[0], myvec.size() * sizeof myvec[0]);
  /* Do stuff with the C-style array for a while
   .
   .
   .
  */
  free(myarr);  /* Don't forget handing back the memory when done. */
}

这会分配一个新的 C 样式数组来保存向量的元素,并将数据复制到位。这样就不需要静态匹配大小了。

当然,这是通用的,所以它只是给你一个void * 来访问你的 C 数组,所以你需要强制转换或将类型更改为实际类型(在这种情况下为BYTE)。

【讨论】:

  • 你应该在 C++ 中使用 new/delete[] 而不是 malloc/free
【解决方案3】:

您可以使用模板参数推导找到数组绑定:

template<typename T, size_t N>
size_t copy(std::vector<T> const& src, T[N] dest) {
    size_t count = std::min(N, src.size());
    std::copy(src.begin(), src.begin()+count, dest);
    return count;
 }

关闭有关未检查内容的 Microsoft 警告。他们的目的是引诱你编写不可移植的代码。

【讨论】:

  • 技术+1。但是“引诱你编写不可移植的代码”? MS 提供了一个符合要求的实现,增加了易于关闭的可选安全功能,人们会抱怨——太棒了。
  • 请参阅警告中的“安全标准 C++ 库”,这不是标准。它背后的想法并没有那么糟糕,但它们在命名上应该是一致的。例如。 stdext::checked_iterator /is/ 正确命名。
【解决方案4】:

你可以这样做:

memcpy(myarr, &(myvec)[0], myvec.size())

编辑:就安全而言,根据this,向量将数据存储在连续的内存段中,因此您“不仅可以使用迭代器,还可以使用指向元素的常规指针的偏移量来访问它们。”

【讨论】:

  • 这将有同样的问题,因为 myvec.size() 比 myarr 大,如果您更改向量和数组的类型,它还有一个无法按预期工作的额外问题。
  • 是的,它只修复了编译时问题。
  • 另外请记住,如果向量的 [0] 为空,则取其地址是不安全的。较新的 VC++ 运行时会大声抱怨这一点(恕我直言)。
  • 你假设 sizeof(BYTE) 是 1。我知道它应该是,但不是我会依赖的假设。
  • 好吧,我不知道 BYTE 是什么(我不做 Windows),但根据定义,C++ 中的 sizeof(char) == 1。
猜你喜欢
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 2017-07-20
相关资源
最近更新 更多