1

我无法使用 struct 元素获得正确大小的向量。元素类是这样定义的(我没有省略任何细节,尽管我认为唯一相关的事实是它是一个包含一个 int 和两个双精度值的类):

class Interval
{
public:
    Interval(int _i = 0, scalar _l = 0, scalar _r = 0) :
        index(_i),
        l(_l),
        r(_r)
    { }

    inline double left(void)    const { return l; }
    inline double right(void)   const { return r; }

    inline bool operator < (const Interval & i2) const { return left() < i2.left(); }

public:
    int index;
    double l;
    double r;

};

然后在一个函数中我有这个代码:

std::vector<Interval> arr(10);
int s1 = arr.size();
int s2 = arr.end() - arr.begin();

我得到的 s1 的值是 15,而 s2 是正确的值 10。这是怎么回事?size() 不应该准确返回元素的数量吗?它不应该与 arr.end() - arr.begin() 相同吗?

任何回应和评论表示赞赏。

4

4 回答 4

1

在键盘中按预期工作

于 2010-10-31T05:56:55.327 回答
1

首先在格式化代码时停止使用 HTML 标签。请改用 [代码] 按钮。

其次,你所描述的是一个无法解释的谜。您应该10s1和中获得相同的值s2。除非您以某种方式设法在其他代码中破坏了向量的完整性(即您运行的代码不是您向我们展示的代码)。

于 2010-10-31T04:19:42.647 回答
0

编辑:既然您已经提供了更多信息,也许我们可以对这种令人困惑的行为有所了解。

您违反了单一定义规则。这样做的结果并没有真正定义,但我们可以根据您观察到的结果做出一些有根据的猜测。

模板函数总是内联声明,因为这是模板参数替换所必需的。当编译器遇到这些函数之一时,它可以选择将其作为内联代码发出或创建一个函数体并调用它。如果它创建了一个函数体,则链接器将负责消除不同翻译单元中的重复定义。链接器并没有做太多的检查来查看明显的重复项在功能上是否等效,它只是通过函数的修饰名称进行检查,这取决于参数的类型;如果类型都具有相同的名称,则假定它们是相同的。由于单一定义规则,它可以做出这种假设。

这就是您可以让源代码中未包含的类定义影响代码结果的方式 - 链接器正在用错误的代码副本替换好的副本。如果编译器生成内联代码,你会得到你期望的结果,如果链接器参与进来,你有 50/50 的机会得到错误的东西。即使你的代码很幸运,其他一些代码现在也会被破坏。


原始答案:向量可能大于请求的大小,但size不会反映该值;您可以使用capacity. 多余的存储将成为内存使用的一部分,但不会初始化元素,并且任何超出结果的访问尝试都size将导致未定义的行为。

于 2010-10-31T04:33:07.540 回答
0

更新:在探索了项目中的代码库之后,我在其他人编写的另一个标题中发现了另一个具有相同名称“Interval”的类(我不好选择这么简单的单词作为我的类名)。该类包含两个双精度数(在我的机器上为 16 个字节,而我的类有 24 个字节),这似乎解释了为什么 size() 调用返回的元素数比实际元素数多 50%。

但我不明白 std::vector 如何被这两个定义混淆(我没有在我的代码中包含该标头,但在包含该标头后,我的标头可能包含在项目的其他部分中),并且end() - begin() 如何使用一个定义,而 size() 如何使用另一个定义。

顺便说一句,为了避免在多程序员项目中发生这种冲突,最好的做法是使用命名空间,对吧?谢谢。

于 2010-10-31T15:33:35.030 回答