8

使用 C++11,我喜欢创建一个布尔数组并立即清除它

bool *mymap = new bool[n];

n 是可变的。

现在,这是否已经清除了数组占用的内存?如果没有,是否有比使用循环遍历所有元素更好的方法来清除数组,将每个元素单独设置为 false?

我考虑过使用 std:memset(),但这需要我知道数组的大小。现在,初学者可能会说:简单,大小是 n*sizeof(bool)。但我不买那个。编译器可能会决定以不同的方式打包它们,甚至将它们打包为位,不是吗?

那么,有没有办法更清楚地告诉数组的大小?我想可能有一个 std:arraysize() 函数简单地返回内存中分配的数组的空间。毕竟,必须以某种方式在运行时维护该信息,否则删除调用不知道要释放多少,对吗?

4

7 回答 7

10

具体问题的答案是否定的,您无法确定 所指向的数组的长度mymap。该语言根本没有为此提供任何机制。

但是,如果您要做的只是确保数组的所有元素都设置为false,那么您所要做的就是对其进行值初始化:

bool* mymap = new bool[n]();
//                       ^^

不幸的是,这仅适用于内置类型的零值。没有等效的方法可以将所有值设置为true.

于 2013-08-14T10:45:23.550 回答
6

你不能以标准的方式做到这一点。但是,不同的编译器支持不同的技巧来做到这一点,例如:

#if defined(_MSC_VER) || ( defined(__GNUC__) && defined(_WIN32) )
      // a dirty MSVC and MinGW hack
      size_t Size = _msize( mymap );
#elif defined(__GNUC__)
      // a dirty glibc hack  
      size_t Size = malloc_usable_size( mymap );
#else
   #error Implement for any other compiler
#endif      

但这些都是真正的黑客,所以要小心。

顺便说一句,std::vector可以帮助您在标准范围内解决您的问题。

于 2013-08-14T10:49:28.783 回答
4

不,编译器不能决定打包它们,除非区域的大小是n * sizeof(bool)- 以任何其他方式执行此操作会破坏将单个数组成员寻址为mymap[x](与 相同*(mymap + x))的能力。

在这种情况下,初学者的建议是正确的。

于 2013-08-14T10:30:59.267 回答
4

不,你不能,因为它实际上不是一个数组。mymap只是指向某个堆内存的普通指针,如果您需要知道大小,您必须自己跟踪它或使用标准容器,例如std::vector.

哦,如果你想要一个更通用的memsetread about变体std::fill

于 2013-08-14T10:28:57.320 回答
2

你可以试试这个:

bool *mymap = new bool[n] ();

但是,这设置为false,您不能使用这种方式设置为true

于 2013-08-14T11:33:12.993 回答
2

让我们假设编译器决定以不同的方式打包。

假设1:编译器将一些位一起打包成一个字节。如果您获取数组中单个元素的地址,则它的类型为 bool。由于编译器不能(通常)推断出您将使用该地址做什么(例如,将其传递给将其传递给库的函数,...),因此不会真正发生在一个字节内的位打包。否则,编译器需要从其打包区域中屏蔽适当的位并将其作为真正的布尔值移动到某处。

假设 2:编译器对一个 bool 值使用超过 sizeof(bool)。极不可能 - 因为那时 sizeof(bool) 会更大。指针操作仍然是可能的,并且在位数组的情况下,需要实现一些其他魔术逻辑。

假设 3:编译器对数组的不同字段使用不同的大小 - 更不可能。所需的管理信息太大了。

从这 3 个想法来看,我认为简单的解决方案是最好的。只是为了确定现在和你程序的所有未来,编写一个小的单元测试来测试它(例如,获取第一个值的地址,将其转换为与 bool 具有相同 sizeof 的类型的指针,计算元素 n 的地址,将该地址转换回 bool 指针,在那里写一些东西并与数组访问进行比较)。然后,如果有变化,您会收到通知 - 但我怀疑它会。


旁注 - 当然编译器总是能够分配比所需更多的内存。但是,该数组仍然具有该大小(它只是放置在更大的内存块中)。

于 2013-08-14T12:40:08.133 回答
2

在赤裸裸的 C++ 中,不,这是不可能的。但是,我们鼓励(并且确实应该)考虑使用一个类来管理内存。

在 C++98 中,您可以使用 aboost::scoped_array或 a std::vector(尽管bool您可能更喜欢 a std::vector<char>)。

在 C++11 中,您应该考虑替换boost::scoped_arraystd::unique_ptr<bool[]>.

问题是在那之前,除了 之外std::vector,没有人知道它们包含的数组的大小;他们只是处理记忆。

在 C++14 中,出现了一个新的竞争者:std::dynarray. 这是一个精简版本,std::vector其大小无法动态调整大小。简而言之,正是您想要的:只有数组及其长度,没有开销。

如果您最喜欢的编译器/工具链还不支持dynarray,您可以轻松地自己实现它:

template <typename T>
class dynarray {
public:
    // methods go here.
private:
    size_t size;
    std::unique_ptr<T[]> array;
}; // class dyn_array
于 2013-08-14T13:06:47.963 回答