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;
}
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您从代码中删除了智能指针,但上面文本中的引用仍然存在。在检查历史记录之前,我有点困惑。如果只声明一个指向类模板专门化的(智能)指针,这可能是一个没有实例化的上下文。对于声明指向某个类型的指针,类型本身不必是完整的。只有当你打开的时候