尽管使用不存在的成员,但程序编译


template <typename T>
void list<T>::copyAll(const list &l)
{
    if(l.isEmpty()) //if the list-to-copy is empty, we're done
    {
        first = last = NULL;
    }
    else
    {
        node *toFollow = l->yhjfrtydfg;
        node *whatever = l.asfqwejfq3fqh23f8hq23r1h23017823r087q1hef;
        while(toFollow != NULL)
        {
            T *newO = new T(*(toFollow->o));
            T here = *newO;
            insertBack(&here);
            toFollow = toFollow->next;
        }
    }
}

该程序编译(与程序的其余部分一起),即使node *toFollow = l->yhjfrtydfg;node *whatever = l.asfqwejfq3fqh23f8hq23r1h23017823r087q1hef;两行显然是疯狂的输入。 这很奇怪,因为捕获了任何其他错误。 有什么帮助吗?

"

依赖名称"(模板中使用的名称,其含义取决于模板参数)仅在实例化模板时解析,而不是在定义模板时解析。如果你不实例化模板,那么它可以包含你喜欢的任何疯狂的名字,只要它在语法上是正确的。

如果程序被实例化,它将无法编译:

list<int> l;
l.copyAll(l); // ERROR
依赖于

模板参数的名称仅在模板实例化后解析。在任何情况下,仅解析非依赖名称。

C++创造了这种"两阶段查找",其中阶段 1 是首次解析的时间,阶段 2 是实例化时间。

例如:

template <typename T>
void frob() {
    foo = 5; // non-dependent, name must exist at this point
    T bar;
    bar.frobnicate = 7; // dependent, name is looked up upon instantiation
    bar->is->a.funny(T::hing); // dependent, likewise looked up later
}

不存在的成员是你最不担心的 - 编译器不会抱怨,因为某些 T 可能确实有这些成员。您混淆的根本原因是编译器只是像其他任何识别符一样看到一个识别器 - 只是您认为没有人会使用它,而且显然没有 T 类型拥有它们,这使得输入"疯狂"。一点也不疯狂。它只是一个标识符。

        T newO = new T(*(toFollow->o));
        insertBack(&newO);
        toFollow = toFollow->next;
彻底

彻底破碎了。首先,您动态分配一个 T,然后尝试从中构造一个堆栈分配的 T?没有 T 以这种方式运行。然后保留指向堆栈分配对象的指针。

最新更新