C++ 非斜体类数组
我希望在不调用构造函数的情况下在堆栈上分配和数组类。下面的示例说明:C++ 非斜体类数组,c++,class,constructor,C++,Class,Constructor,我希望在不调用构造函数的情况下在堆栈上分配和数组类。下面的示例说明: template<class t,int SetNum> class set { private: t Storage[SetNum]; }; class myClass { private: int* Array; public: myClass() { Array=new int[10]; } } int main() { set<myCl
template<class t,int SetNum> class set
{
private:
t Storage[SetNum];
};
class myClass
{
private:
int* Array;
public:
myClass()
{
Array=new int[10];
}
}
int main()
{
set<myClass,10> Set;
}
模板类集合
{
私人:
t存储[SetNum];
};
类myClass
{
私人:
int*数组;
公众:
myClass()
{
数组=新整数[10];
}
}
int main()
{
集合;
}
我不想为调用
myClass
的构造函数时出现的Array
分配10个新的int,但仍然希望为myClass
分配空间。您必须有一个无符号字符的数组(或类似的数组)作为元素的“后备存储”,然后调用placementnew
操作符(参见示例)在那里构建实例(顺便说一下,std::vector
已经在这样做了)
警告:如果使用placement new,您有责任手动取消分配使用它创建的对象,并显式调用析构函数;此外,传递到placement new的指针必须与正在创建的对象正确对齐,否则可能会发生错误
另见
使用所述技术构建的std::array
和std::vector
的扭曲混合示例(需要C++11才能使用联合
技巧):
编辑有一个。问题模棱两可。是否不分配myClass数组或int数组?创建对象数组将自动调用默认构造函数。这是无法避免的。在您认为需要避免调用默认构造函数的情况下,您想做什么?@DumpHole问题清楚地说明了“我不想为数组
分配10个新的整数,当myClass
的构造函数在一开始被调用时,“@code Guru”他问“而不调用构造函数”。因此,我不清楚问题是阻止调用构造函数,还是阻止分配int数组。不是每个对象都可以放在任何地址,有些对象对它们可以放在的地址有特定的限制(例如,在某些平台上,32位整数只能放在4字节的整数倍数的地址上)。为了解决这类问题,我将使“后备存储器”的大小(t)
大于所需的大小,然后使用alignof
operator/align
函数来确定实际用作t
类型对象的存储器的第一个地址。。。。实际上,您可以使用另一个技巧:您的“备份存储”可以留在联合体中,其中包含一个t
类型的元素,该元素不会自动构造/销毁(C++11,[class.union]^2-4),但是可以保证它作为一个整体对您的类型t
正确对齐。有一个问题是,带有构造函数的类不能在联合中使用。@user1204406:这一限制在C++11中已经取消,这就是为什么我多次说这样的代码需要C++11才能正确编译的原因。
#include <cstddef>
#include <memory>
#include <stdexcept>
#include <iostream>
template<typename T, std::size_t N>
class array_noinit
{
union storage_helper
{
private:
// this member assures that the storage is properly aligned
T t;
public:
unsigned char storage[sizeof(T)*N];
// needed because T's constructor/destructor is implicitly deleted
storage_helper() { };
~storage_helper() { };
};
storage_helper s;
std::size_t _size;
T * _storage;
public:
array_noinit() :
_size(0), _storage((T*)s.storage)
{}
~array_noinit()
{
while(_size>0)
pop_back();
}
void push_back(const T & elem)
{
if(_size>=N)
throw std::runtime_error("Not enough capacity.");
new(_storage+_size) T(elem);
_size++;
}
void pop_back()
{
if(_size>0)
{
_size--;
_storage[_size].~T();
}
}
T & at(std::size_t Idx)
{
if(Idx>=_size)
throw std::out_of_range("Idx out of range.");
return _storage[Idx];
}
std::size_t size() const
{
return _size;
}
std::size_t capacity() const
{
return N;
}
};
class A
{
int _i;
public:
A(int i) : _i(i)
{
std::cout<<"In A constructor - "<<_i<<"\n";
}
A(const A & right)
: _i(right._i)
{
std::cout<<"In A copy constructor - "<<_i<<"\n";
}
~A()
{
std::cout<<"In A destructor - "<<_i<<"\n";
}
};
int main()
{
std::cout<<"With ints\n";
array_noinit<int, 4> arr;
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
arr.push_back(4);
for(std::size_t i=0; i<4; i++)
std::cout<<arr.at(i)<<" ";
std::cout<<"\n";
std::cout<<"With a class - we don't add anything\n";
array_noinit<A, 10> arr2;
std::cout<<"With a class - now we add stuff\n";
array_noinit<A, 10> arr3;
arr3.push_back(A(1));
arr3.push_back(A(2));
arr3.push_back(A(3));
return 0;
}
With ints
1 2 3 4
With a class - we don't add anything
With a class - now we add stuff
In A constructor - 1
In A copy constructor - 1
In A destructor - 1
In A constructor - 2
In A copy constructor - 2
In A destructor - 2
In A constructor - 3
In A copy constructor - 3
In A destructor - 3
In A destructor - 3
In A destructor - 2
In A destructor - 1