C++ 初始化嵌套模板
我正在努力学习更多关于模板的知识,但遇到了一个似乎无法解决的问题。目前,下面的班级运转良好C++ 初始化嵌套模板,c++,templates,constructor,C++,Templates,Constructor,我正在努力学习更多关于模板的知识,但遇到了一个似乎无法解决的问题。目前,下面的班级运转良好 #include <iostream> #include <vector> #include <cstring> using namespace std; template <class T, int s> class myArray{ public: T* data; inline T& operator[](const int
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
template <class T, int s>
class myArray{
public:
T* data;
inline T& operator[](const int i){return data[i];}
myArray(){
data=new T[s];
}
myArray(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArray& operator=(const myArray& other){
data=new T[s];
copy(other.data,other.data+s,data);
return *this;
}
~myArray(){delete [] data;}
};
我认为当数据不是int类型(即维度大于1的任何数组上)时,这应该失败,但是它不是。当数组为正方形时,它会工作,但如果不是,则某些条目不会设置为10。有人知道标准向量类是如何实现这一点的吗?任何帮助都将是惊人的。谢谢 好吧,试试这样:
myArray()
: data(new T[s]()) // value-initialization!
{
}
myArray(T const & val)
: data(new T[s]) // default-initialization suffices
{
std::fill(data, data + s, val);
}
如果你对可变模板感兴趣,你可能会编造一些更奇怪的涉及可变填充初始值设定项列表的东西,但我认为我们已经做了足够一周的学习
请注意使用
new
的基本缺陷:任何一个版本都要求类T
可以在某种“默认”状态下实例化,并且它是可赋值的,即使我们在第二个版本中从未要求默认状态。这就是为什么“真实”库将内存分配和对象构造分开,并且除非是放置版本,否则您永远不会看到新的表达式。std::vector在内存块上使用新的放置。在第二行代码中分配内存后,它构造数据
这项技术也适用于您。注意放置新的位置,因为它也需要手动调用析构函数
这是一条半途而废的路线,没有新的布局:
template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
AllocateSpace(N); // write this, just allocates space
for (int i = 0; i < N; ++i)
{
Element(i) = T( constructFromAnythingElse );
}
}
模板
显式MyArray(U const&constructFromAnythingElse)
{
AllocateSpace(N);//写这个,只分配空间
对于(int i=0;i
使用placement new,您必须首先分配内存,然后就地构造,然后记住在最后销毁每个元素
与放置新路由相比,上面的方法是半途而废的,因为我们首先构建每个元素,然后构建另一个元素,并使用operator=
覆盖它
通过使其成为任意类型上的模板构造函数,我们不需要依靠多次转换将多个级别下放到数组中。朴素的版本(取T常量&)不起作用,因为要构造一个由T数组组成的数组,最外层的版本需要一个由T数组组成的数组作为参数,而最外层的版本需要一个由T数组组成的数组作为参数,最外层的版本需要一个由T数组组成的数组作为参数,而最外层的版本需要一个由T组成的数组——用户定义的构造层次太多了
使用上述模板构造函数,数组的数组接受任何类型作为构造函数。正如T数组一样,T数组也是如此。最后,T被传递到构建T数组最外层数组的任何地方,如果它不喜欢,就会得到一条几乎完全无法读取的编译器错误消息。对包含其他数组的数组进行专门化。要做到这一点,您需要在通用和专用MyArray中使用一些常见的实现类: 常见实现(我为您做了一些修复-请参见!!!注释): 以及myArray的myArray专用版本-另请参见
value\u type
和setAll
中的差异:
template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef typename myArray<T,s2>::value_type value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
}
};
模板
类myArray:private myArrayImpl{
typedef myArrayImpl Impl;
公众:
使用Impl::operator[];
myArray():Impl(){}
typedef typename myArray::value\u type value\u type;/!!!
显式myArray(常量值\类型和值){
setAll(值);
}
void setAll(常量值\类型和值){
对于每个(this->data,this->data+s1,[value](myArray&v){v.setAll(value);});
}
};
使用方法:
int main() {
myArray<myArray<myArray<int,7>,8>,9> a(7);
std::cout << a[0][0][0] << std::endl;
std::cout << a[8][7][6] << std::endl;
}
intmain(){
mya阵列(7);
std::cout您的赋值运算符没有清除旧数据。谢谢。我这样做了,并且在“myArray”具有2个或更少维度时它会工作。对于更大的数组,我会得到“调用“myArray::myArray(int)”时没有匹配的函数”。如果有人有机会看一眼,这是我的新代码:谢谢!为什么不使用模板显式myArray(U const&U)?也就是说,接受任何类型,如果它不能用于构建内容,就会得到一个错误。实际上,我们想说的是“任何可以用于构建我的内容的东西对我来说都是公平的游戏”--如果您的内容是myArrays,您的工作正常。@Yakk您可能是对的-我没有检查-但这似乎是合理的…我只是担心它太笼统了。此外,我的解决方案中可以使用任何可转换为值的类型\u type-并且此转换只会执行一次-不是针对[multi]中的每个单元格阵列。这是您的解决方案的一个很好的功能!+1
template<typename U>
explicit MyArray( U const& constructFromAnythingElse )
{
AllocateSpace(N); // write this, just allocates space
for (int i = 0; i < N; ++i)
{
Element(i) = T( constructFromAnythingElse );
}
}
template <class T, int s>
class myArrayImpl {
public:
T* data;
T& operator[](int i){return data[i];} //!!! const before int not needed
const T& operator[](int i) const {return data[i];} //!!! was missing
myArrayImpl(){
data=new T[s]();
}
myArrayImpl(const myArrayImpl & other){
data=new T[s];
copy(other.data,other.data+s,data);
}
myArrayImpl& operator=(const myArrayImpl& other){
T* olddata = data; // !!! need to store old data
data=new T[s];
copy(other.data,other.data+s,data);
delete [] olddata; //!!! to delete it after copying
return *this;
}
~myArrayImpl(){delete [] data;}
};
template <class T, int s>
class myArray : private myArrayImpl<T,s> {
typedef myArrayImpl<T,s> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef T value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
fill(this->data, this->data + s, value);
}
};
template <class T, int s1, int s2>
class myArray<myArray<T,s2>,s1> : private myArrayImpl<myArray<T,s2>,s1> {
typedef myArrayImpl<myArray<T,s2>,s1> Impl;
public:
using Impl::operator[];
myArray() : Impl() {}
typedef typename myArray<T,s2>::value_type value_type; // !!!
explicit myArray(const value_type& value) {
setAll(value);
}
void setAll(const value_type& value) {
for_each(this->data, this->data + s1, [value](myArray<T,s2>& v) { v.setAll(value); });
}
};
int main() {
myArray<myArray<myArray<int,7>,8>,9> a(7);
std::cout << a[0][0][0] << std::endl;
std::cout << a[8][7][6] << std::endl;
}