Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类模板的动态实例化是显式的还是隐式的?_C++_Templates_Pointers_Explicit Instantiation - Fatal编程技术网

C++ 类模板的动态实例化是显式的还是隐式的?

C++ 类模板的动态实例化是显式的还是隐式的?,c++,templates,pointers,explicit-instantiation,C++,Templates,Pointers,Explicit Instantiation,如果我有一个类模板,并且我使用一个智能指针指向一个专门实例的动态分配实例,那么这会导致编译器定义整个类模板,还是会在实例化之前等待从指针调用成员函数 template <class T> class Test { public: void nothing(); void operation(); static const int value; }; template <class T> const int Tes

如果我有一个类模板,并且我使用一个智能指针指向一个专门实例的动态分配实例,那么这会导致编译器定义整个类模板,还是会在实例化之前等待从指针调用成员函数

template <class T>
class Test {
    public:
        void nothing();
        void operation();

        static const int value;
};

template <class T>
const int Test<T>::value = 100;

template <class T>
void Test<T>::nothing() {
   /* invalid code */
   int n = 2.5f;
}

template <class T>
void Test<T>::operation() {
    double x = 2.5 * value;
}

int main() {
    std::unique_ptr<Test<int>> ptr = new Test<int>();  // mark1
    ptr->operation(); // mark2
    return 0;
}
模板
课堂测试{
公众:
什么都不作废();
无效操作();
静态常量int值;
};
模板
常量int测试::值=100;
模板
无效测试::nothing(){
/*无效代码*/
int n=2.5f;
}
模板
无效测试::操作(){
双x=2.5*值;
}
int main(){
std::unique_ptr ptr=new Test();//标记1
ptr->operation();//标记2
返回0;
}
  • 整个类模板是否在mark1处实例化

  • 如果不是,这是否意味着此代码将正确编译,并且不会实例化成员函数Test::nothing()

  • template <class T>
    class Test {
        public:
            void nothing();
            void operation();
    
            static const int value;
    };
    
    template <class T>
    const int Test<T>::value = 100;
    
    template <class T>
    void Test<T>::nothing() {
       /* invalid code */
       int n = 2.5f;
    }
    
    template <class T>
    void Test<T>::operation() {
        double x = 2.5 * value;
    }
    
    int main() {
        std::unique_ptr<Test<int>> ptr = new Test<int>();  // mark1
        ptr->operation(); // mark2
        return 0;
    }
    
    整个类模板是否在mark1处实例化

    对。类模板是隐式实例化的-只有类模板,而不是它的所有成员

    如果不是,这是否意味着此代码将正确编译,并且不会实例化成员函数Test::nothing()

    template <class T>
    class Test {
        public:
            void nothing();
            void operation();
    
            static const int value;
    };
    
    template <class T>
    const int Test<T>::value = 100;
    
    template <class T>
    void Test<T>::nothing() {
       /* invalid code */
       int n = 2.5f;
    }
    
    template <class T>
    void Test<T>::operation() {
        double x = 2.5 * value;
    }
    
    int main() {
        std::unique_ptr<Test<int>> ptr = new Test<int>();  // mark1
        ptr->operation(); // mark2
        return 0;
    }
    
    not并不意味着,如果未使用
    nothing()
    ,则它不是实例化的

    整个类模板是否在mark1处实例化

    对。类模板是隐式实例化的-只有类模板,而不是它的所有成员

    如果不是,这是否意味着此代码将正确编译,并且不会实例化成员函数Test::nothing()

    template <class T>
    class Test {
        public:
            void nothing();
            void operation();
    
            static const int value;
    };
    
    template <class T>
    const int Test<T>::value = 100;
    
    template <class T>
    void Test<T>::nothing() {
       /* invalid code */
       int n = 2.5f;
    }
    
    template <class T>
    void Test<T>::operation() {
        double x = 2.5 * value;
    }
    
    int main() {
        std::unique_ptr<Test<int>> ptr = new Test<int>();  // mark1
        ptr->operation(); // mark2
        return 0;
    }
    

    not并不意味着,如果没有使用
    nothing()
    ,它就不是instantite。

    这个问题的完整答案可能在很大程度上取决于您使用的编译器

    //mark1
    处,编译器将注意到至少需要实例化
    Test
    类的一部分。无论它是在那个时候,还是在以后的阶段,都取决于编译器设计者

    //mark2
    ,显然需要
    Test.operation()
    ,它要么被标记以供以后实例化,要么当场创建,这同样取决于编译器设计者的决定


    由于从未引用过
    Test.nothing()
    ,编译器可以自由地实例化或不实例化它。一些较旧的编译器盲目地实例化了整个类,但我怀疑大多数现代编译器只会实例化它们可以证明是必要的(或者至少它们不能证明是不必要的)。不过,在编译器中发生的位置取决于编译器设计者构建编译器的方式。

    对此的完整答案可能在很大程度上取决于您使用的编译器

    //mark1
    处,编译器将注意到至少需要实例化
    Test
    类的一部分。无论它是在那个时候,还是在以后的阶段,都取决于编译器设计者

    //mark2
    ,显然需要
    Test.operation()
    ,它要么被标记以供以后实例化,要么当场创建,这同样取决于编译器设计者的决定


    由于从未引用过
    Test.nothing()
    ,编译器可以自由地实例化或不实例化它。一些较旧的编译器盲目地实例化了整个类,但我怀疑大多数现代编译器只会实例化它们可以证明是必要的(或者至少它们不能证明是不必要的)。不过,在编译器中发生的情况取决于编译器设计者构建编译器的方式。

    因此,对于我正在使用的编译器(MS Visual C++),我的假设是正确的,对于问题中给出的代码,类模板成员实例化不会在
    //mark1
    处进行,而是在
    //mark2
    测试处进行。编译器不会创建nothing()

    然而,我似乎遗漏了我所经历的问题的一个关键部分。我的实际类是虚拟层次结构的一部分,根据MSDN帮助库,所有虚拟成员都在对象创建时实例化。因此,在上面的示例中,如果两个成员函数,即
    operation()
    nothing()
    ,都是虚拟的,那么在
    //mark2
    处,编译器将尝试为这两个函数生成代码,
    nothing()
    的验证将失败


    因此,对于我正在使用的编译器(MS Visual C++),我的假设是正确的,对于问题中给出的代码,类模板成员实例化不会发生在
    //mark1
    处,而是发生在
    //mark2
    测试处。编译器不会创建任何()

    然而,我似乎遗漏了我所经历的问题的一个关键部分。我的实际类是虚拟层次结构的一部分,根据MSDN帮助库,所有虚拟成员都在对象创建时实例化。因此,在上面的示例中,如果两个成员函数,即
    operation()
    nothing()
    ,都是虚拟的,那么在
    //mark2
    处,编译器将尝试为这两个函数生成代码,
    nothing()
    的验证将失败


    实际上,
    intn=2.5f并不完全是“无效代码”。它只是无意义的。AFAIK只有您实际使用的成员函数被实例化。@stefan您从代码中删除了智能指针,但上面文本中的引用仍然存在。在检查历史记录之前,我有点困惑。如果只声明一个指向类模板专门化的(智能)指针,这可能是一个没有实例化的上下文。对于声明指向某个类型的指针,类型本身不必是完整的。只有当你打开的时候