模板是如何实例化的? 这是C++入门第五版的练习:

模板是如何实例化的? 这是C++入门第五版的练习:,c++,templates,instantiation,C++,Templates,Instantiation,练习16.27:对于每个标记的语句,解释什么,如果有的话, 实例化会发生。如果模板被实例化,解释原因;如果 不,解释为什么不。第677页 模板类堆栈{}; 空f1(堆栈);//(a) 课堂练习{ 堆栈&rsd;/(b) 堆栈si;/(c) }; int main(){ 堆栈*sc;//(d) f1(*sc);//(e) int iObj=sizeof(Stack);/(f) } 以下是我尝试过的: (a) 堆栈已实例化,但未实例化其任何成员 (b) 堆栈已实例化,但未实例化其任何成员 (c)

练习16.27:对于每个标记的语句,解释什么,如果有的话, 实例化会发生。如果模板被实例化,解释原因;如果 不,解释为什么不。第677页

模板类堆栈{};
空f1(堆栈);//(a)
课堂练习{
堆栈&rsd;/(b)
堆栈si;/(c)
};
int main(){
堆栈*sc;//(d)
f1(*sc);//(e)
int iObj=sizeof(Stack);/(f)
}
以下是我尝试过的:

(a)
堆栈
已实例化,但未实例化其任何成员

(b)
堆栈
已实例化,但未实例化其任何成员

(c)
堆栈
及其默认构造函数被实例化

(d) (e)完全不知道

(f)
堆栈
已实例化,但未实例化其任何成员


我说得对吗?有人能告诉我这段代码是如何实例化的吗

关于e和d,我将引用标准14.7.1

除非明确指定了函数模板专用化 实例化或显式专用化的函数模板 专门化是在指定专门化时隐式实例化的 在需要函数定义存在的上下文中引用。 除非调用是对函数模板的显式专门化或 显式专用类模板的成员函数 函数模板或函数的成员函数的默认参数 类模板在调用函数时隐式实例化 在需要默认参数值的上下文中

示例也来自标准

template<class T> struct Z {
    void f();
    void g();
};

void h() {
    Z<int> a;     // instantiation of class Z<int> required
    Z<char>* p;   // instantiation of class Z<char> not required
    Z<double>* q; // instantiation of class Z<double> not required
    a.f();        // instantiation of Z<int>::f() required
    p->g();       // instantiation of class Z<char> required, and instantiation of Z<char>::g() required
}
模板结构Z{
无效f();
void g();
};
void h(){
Z a;//需要实例化类Z
Z*p;//不需要实例化类Z
Z*q;//不需要实例化类Z
a、 f();//需要实例化Z::f()
p->g();//需要实例化类Z,需要实例化Z::g()
}

这意味着在d中不会发生实例化。如果该函数实际需要从该类型调用函数(可以是复制构造函数或函数内部调用的任何其他函数),则它将在e中实例化。

在您的特定情况下,声明并不意味着实例化

#include <iostream>
using namespace std;


template <typename T> class Stack {
  typedef typename T::ThisDoesntExist StaticAssert; // T::NotExisting doesn't exist at all!
};


void f1(Stack<char>); // No instantiation, compiles

class Exercise {
  Stack<double> &rsd; // No instantiation, compiles (references don't need instantiation, are similar to pointers in this)

  Stack<int>    si; // Instantiation! Doesn't compile!!
};


int main(){

  Stack<char> *sc; // No Instantiation, this compiles successfully since a pointer doesn't need instantiation

  f1(*sc); // Instantiation of Stack<char>! Doesn't compile!!

  int iObj = sizeof(Stack< std::string >); // Instantiation of Stack<std::string>, doesn't compile!!

}
#包括
使用名称空间std;
模板类堆栈{
typedef typename T::ThisDoesTextist StaticAssert;//T::NotExisting根本不存在!
};
空f1(堆栈);//没有实例化,编译
课堂练习{
Stack&rsd;//无实例化,编译(引用不需要实例化,类似于此中的指针)
堆栈si;//实例化!未编译!!
};
int main(){
Stack*sc;//没有实例化,这将成功编译,因为指针不需要实例化
f1(*sc);//堆栈的实例化!未编译!!
int iObj=sizeof(Stack);//堆栈的实例化,不编译!!
}
请注意指针/引用的内容:它们不需要实例化,因为实际上没有分配任何数据(指针只是包含地址的几个字节,不需要存储所有数据..请查看示例)


只有在分配了内容时模板才必须完全解析(这发生在编译时,这就是为什么它们通常需要声明和定义的原因。目前还没有链接阶段)

如果有疑问,可以添加依赖的静态断言(或类似于强制编译时错误的东西),例如,断言
T
void
。成员函数中失败的断言将告诉您成员函数已实例化。当你知道发生了什么,解释为什么会发生就容易多了。成员函数外的失败断言同样会告诉您类本身已实例化。@hvd Thx man。因为我以前从未使用过断言。我试图理解这种方法。在这种情况下,由于所有复制和控制成员都是合成版本,我是否应该像默认构造函数一样编写自定义版本并将断言放入其中?如果它不编译,就意味着这个默认构造函数被实例化了。我说的对吗?是的,这就是我的意思。您首先检查(使用DavidKernin的答案)在哪些情况下类本身被实例化。然后,您可以将类(从答案中复制断言样式)更改为,例如,
模板类堆栈{public:Stack(){typedef typename T::thisdesntextest StaticAssert;}
检测默认构造函数的使用位置。我以前从未使用过断言。在尝试编译语句时
Stack si
从您的代码中,有人抱怨
'int'不是类、结构或联合类型
。如何理解它?如果删除所有“不编译”行并注释掉这些行,它应该编译:。另外:该特定行需要知道练习对象的大小。如果您不实例化si对象,那么您无法提前知道,而对于指针来说,这并不重要(在x64系统上,指针是8字节宽的)。因此。。。无论指针指向哪个对象,指针的大小都是固定的,始终为8字节。编译器将始终使用8字节的空间来存储指针,即使在实例化之前也是如此。但是对于一个对象,编译器在实例化之前不会知道它的大小。你是说这个吗?在x64系统上,8字节。在32位x86系统上,4个字节,依此类推,具体取决于体系结构。指针的类型很重要,但事先知道应该分配多少空间并不重要。
#include <iostream>
using namespace std;


template <typename T> class Stack {
  typedef typename T::ThisDoesntExist StaticAssert; // T::NotExisting doesn't exist at all!
};


void f1(Stack<char>); // No instantiation, compiles

class Exercise {
  Stack<double> &rsd; // No instantiation, compiles (references don't need instantiation, are similar to pointers in this)

  Stack<int>    si; // Instantiation! Doesn't compile!!
};


int main(){

  Stack<char> *sc; // No Instantiation, this compiles successfully since a pointer doesn't need instantiation

  f1(*sc); // Instantiation of Stack<char>! Doesn't compile!!

  int iObj = sizeof(Stack< std::string >); // Instantiation of Stack<std::string>, doesn't compile!!

}