有没有一种安全的方法可以迭代 std::unique_ptr<int[]>?

Is there a safe way to iterate over std::unique_ptr<int[]>?

本文关键字:ptr unique lt int gt std 一种 安全 迭代 方法 有没有      更新时间:2023-10-16

在下面的代码中,我收到MSVC (C4996)的警告,指出std::copy(errors.begin(),errors.end(),pErrors.get());不安全。它写入原始指针。有没有一种优雅而安全的方式来迭代元素?

主要目标是为调用遗留函数准备一个内置数组:

#include <iostream>
#include <initializer_list>
#include <memory>
#include <algorithm>
void print_errors_old_function(int argument_count,int* pErrors)
{
    for (int i=0;i<argument_count;++i) { std::cerr << "Error" << pErrors[i] << " "; }
}
void print_errors(std::initializer_list<int> errors)
{
    std::unique_ptr<int[]> pErrors{new int[errors.size()]};
    std::copy(errors.begin(),errors.end(),pErrors.get()); // warning C4996
    print_errors_old_function(errors.size(),pErrors.get());
}
int main()
{
    print_errors({234,253,334});
    return 0;
}

似乎基于范围的 for 循环对于std::unique_ptr<int[]>是不可能的,并且常规的 for 循环的可读性可能不如 std::copy .

你不需要std::unique_ptr . std::vector可以正常工作,因为&v[0]保证为您提供指向内部缓冲区的指针,当然,它还具有可用于与 C 函数交互的size()成员函数。从C++11开始,还有data(),看起来比&v[0]更好。

#include <iostream>
#include <initializer_list>
#include <vector>
void print_errors_old_function(int argument_count,int* pErrors)
{
    for (int i=0;i<argument_count;++i) { std::cerr << "Error" << pErrors[i] << " "; }
}
void print_errors(std::initializer_list<int> errors)
{
    std::vector<int> vErrors(errors);
    print_errors_old_function(vErrors.size(), &vErrors[0] /* or vErrors.data() in C+11 */ );
}
int main()
{
    print_errors({234,253,334});
    return 0;
}

注意如何也摆脱警告。

另一个答案是正确的,但请注意,函数是这样的:

void print_errors_old_function(int argument_count,int* pErrors)
{
    for (int i=0;i<argument_count;++i) { std::cerr << "Error" << pErrors[i] << " "; }
    delete[] pErrors; // note this function effectively "consumes" the input
}

您将无法使用这种方法,因为无法释放vector内存的所有权。你必须使用std::unique_ptr你在问题中的方式,但你必须使用pErrors.release()而不是pErrors.get()

视觉C++抱怨是因为在标准中定义的几个函数上,但它认为它们是"不安全的",这使得符合标准的代码不可编译。有时,Microsoft会提供仅在 Visual C++ 上可用的解决方法。

您可以执行的操作(选择以下选项之一):

  • 利用建议Microsoft的解决方法
  • 禁用 SDL 检查(这些检查会将这些警告转换为错误)
  • 在项目中定义_SCL_SECURE_NO_WARNINGS。(禁用这些警告)