我能告诉C ++中用“new type [n]”创建的数组的大小吗?

时间:2013-08-14 10:26:09

标签: c++ c++11

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

bool *mymap = new bool[n];

n是可变的。

现在,这是否已经清除了阵列占用的内存?如果没有,是否有更好的方法来清除数组,而不是在所有元素上使用循环,将每个元素分别设置为false?

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

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

7 个答案:

答案 0 :(得分:10)

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

但是如果你想要做的就是确保数组的所有元素都设置为false,那么你所要做的就是将值初始化:

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

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

答案 1 :(得分: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可以帮助您在标准范围内解决问题。

答案 2 :(得分:4)

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

哦,如果你想要memset更通用的变体,请阅读std::fill

答案 3 :(得分:4)

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

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

答案 4 :(得分:2)

你可以试试这个:

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

但是设置为false并且您无法使用这种方式设置为true

答案 5 :(得分:2)

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

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

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

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

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


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

答案 6 :(得分:2)

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

在C ++ 98中,您可以使用boost::scoped_arraystd::vector(但bool可能更喜欢std::vector<char>)。

在C ++ 11中,您应该考虑将boost::scoped_array替换为std::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