【问题标题】:What is the cleanest method for simple scope management of an array with in C++11在 C++11 中对数组进行简单范围管理的最简洁方法是什么
【发布时间】:2012-03-13 20:06:13
【问题描述】:

我正在寻找一种使用 C++11 中引入的新指针模板来管理数组范围的干净方法,这里的典型场景是调用 win32 api 函数时。

我在这里发帖是因为尽管有很多关于更复杂问题的讨论,但这个相对简单的场景似乎没有被讨论过,我想知道是否有比我现在开始做的更好的选择。

#include <memory>

void Win32ApiFunction(void* arr, int*size)
{
    if(arr==NULL)
        *size = 10;
    else
    {
        memset(arr,'x',10);
        ((char*)arr)[9]='\0';
    }
}

void main(void)
{
    // common to old and new
    int size;
    Win32ApiFunction(NULL,&size);

    // old style - till now I have done this for scope reasons
    if(char* data = new char[size])
    {
        Win32ApiFunction(data,&size);
        // other processing
        delete [] data;
    }

    // new style - note additional braces to approximate
    // the previous scope - is there a better equivalent to the above?
    {
        std::unique_ptr<char[]> data1(new char[size]);
        if(data1)
        {
            Win32ApiFunction(data1.get(),&size);
            // other processing
        }
    }
}

【问题讨论】:

  • 在任何一种情况下,new 都会在分配失败时抛出异常,而不是返回 0。
  • 对于大多数真正的Win32 API函数,在第一次调用之前需要将“size”初始化为0。
  • 如果您需要在第二次调用之前对数组进行零初始化,那么std::vector&lt;char&gt; 会更好(因为它会自动且快速地执行此操作)。如果您不需要将数组归零,那么您所拥有的将优于 std::vector&lt;char&gt;,因为它不会花费周期进行不需要的零初始化。而且,如果您不在需要最高性能的环境中,那么使用哪一种都没有关系。
  • 别忘了new char[size]()

标签: c++ arrays memory-management c++11 unique-ptr


【解决方案1】:

最干净的方法是使用std::vector,即使C++98也保证它与C风格的数组兼容(即存储为单个连续块),你只需要传递指向第一个元素的指针给你的Win32ApiFunction

std::vector<char> data(size);
Win32ApiFunction(&data[0], &size);

在 C++11 中,有一个特殊的成员函数 std::vector&lt;T&gt;::data(),它返回指向数组开头的指针(因此您无需担心向量值类型的重载 operator&amp; () 并使用 std::addressof ,请参阅 How can I reliably get an object's address when operator& is overloaded? 以了解 operator&amp;() 重载的 C++98 问题)。

【讨论】:

  • 我想你想要 std::vector 在这里。
  • 请注意,在 C++11 中有一个特殊的方法:std::vector&lt;T&gt;::data,它将返回指向数组开头的指针。
  • API 调用可能会返回 size == 0。在这种情况下,您的向量有零个元素,并且未定义对第一个元素 &data[0] 的引用。它可能并且经常在某些平台上正常工作,但调试构建可能会由于越界访问而失败。我相信这是将 data() 添加到 C++11 的原因之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-11
  • 2010-09-12
  • 1970-01-01
  • 2012-05-03
  • 2012-05-02
  • 1970-01-01
相关资源
最近更新 更多