【问题标题】:What is the most efficient way to check if a C++ container is empty? [closed]检查 C++ 容器是否为空的最有效方法是什么? [关闭]
【发布时间】:2017-09-15 23:20:36
【问题描述】:

以下哪项检查容器是否为空最有效? 假设“c”是 C++ Containers 库的任何容器部分

1. c.begin()==c.end()
2. c.empty() 
3. c.size()==0

在 2 的情况下,文档显示“Checks if the container has no elements,ie是否begin() == end()”但没有说明是否empty() 实现为 begin() == end()。那么,empty() 究竟是如何实现的呢?

为什么会这样?

sizeof(c) == 0

【问题讨论】:

  • 因为sizeof是对象的大小而不是元素的数量,也请不要在没有展示您当前的尝试和理解的情况下在这里发布您的测验/作业问题
  • 调用 empty() 将使阅读代码的任何人都清楚其意图,我怀疑其他人会更有效率。
  • 如您所见,有几个问题一个问题,并不是所有问题都得到了回答。
  • empty() 的实现方式是一个实现细节,具体取决于谁提供您的标准库实现。您不能指望它的性能在所有平台上的所有编译器中都是一致的。但它可能很便宜。除非/直到您的分析表明这是一个瓶颈,否则更喜欢它。

标签: c++ stl


【解决方案1】:

检查空容器的所有三个选项或多或少是等效的。使用empty() 可以最明显地显示您的意图(如 cmets 中所示),并且作为一点奖励,它甚至是最短的写法(适用于像我这样的懒人......)。

它是如何实现的?供应商特定的,可能是内联的。选项 1 用于并非不可能,但不能保证。

类或多或少是任何适当类型的数据的集合。它们的内部结构必须在编译时知道,因此必须总是固定的*)——因此,它们的大小(必须是...)。

sizeof(c) 将返回这个固定大小,即使对于容器,无论您在其中放置了多少元素,这就是为什么 sizeof(c) 是错误的(实际上,它永远不会得到 0,正如 NathanOliver 提到的那样在他的回答中,但即使可以,它也会一直为 0,即使容器 not 为空)。


为了说明sizeof:让我们看一些标准容器(我将省略公共接口,只关注数据成员):

template <typename T>
vector
{
    size_t capacity;
    size_t size;
    T* data;
};

这大概是一个矢量所需的全部。包含的数据存储在堆上某处分配的某个数组中,唯一属于向量 class 的部分是指向的指针。 sizeof 这样的向量可能是 32(假设 size_t 和指针为 8 字节大,就像在现代 64 位硬件上一样,所以你得到 24 字节的成员和另外 8 字节的指向 vtable 的指针,前提是这个向量类拥有虚拟成员)——不断

template<typename T>
class list
{
    class Node
    {
       Node* next;
       Node* previous;
       T data;
    };
    Node* head;
    Node* tail;
};

再次 - 两个指针仅在内部,内容分配在堆上某处的节点内。 head 和/或 tail 可能 是一些虚拟节点,以便在 begin()end() 中更容易使用,但如果是这样,那是一个实现细节...... sizeof(list) 将最有可能是 24 岁——一直在。


*) “总是修复” - 在编译期间和编译程序的运行期间;如果您为不同的机器编译,大小可能会有所不同(例如,如果为较旧的 32 位硬件编译,上面的向量和列表可能有 16 和 12 的大小)。大小甚至可以从一个编译到另一个 e. G。由于更改了编译器标志(例如更改默认对齐方式,...)。但是在编译过程中,一旦编译,sizeof 就修复了。

【讨论】:

    【解决方案2】:

    为什么sizeof(c) == 0 错了?每个对象都必须有一个地址,这意味着它的大小必须为 1 或更大。这意味着sizeof(anything) 总是大于0。因为sizeof(c) == 0 永远不会是真的。


    还要注意sizeof 是编译时操作。它无法为您提供仅在运行时才知道的任何内容的大小。比如

    char * foo = new char[20];
    std::cout << sizeof(foo);
    

    总是会给你指针的大小(在大多数平台上是 4 或 8),而不是指针指向的内存大小。

    【讨论】:

    • 空基类也有地址,只是它们可能与其他子对象共享该地址。
    • @aschepler 好点。我会删除它
    • 我要补充一点,sizeof() 是对象的编译时大小,您不能以任何方式使用它来确定运行时信息。
    • 虽然严格正确,但这并不是尝试使用sizeof 执行此任务的真正原因是错误的。原因是sizeof 的含义不同。
    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 2013-02-18
    • 2019-01-10
    • 1970-01-01
    相关资源
    最近更新 更多