如何复制元素为const类型的数组?
我做一个数组模板类,构造方式需要原封不动复制c++系统数组,但是当数组元素为const类型时却出现了operator =()调用时的左值问题,如何解决这个问题?请高手指教。下面是我的代码例子:
template<typename TElementType>class CArray //数组类
{
public:
CArray(TElementType * aElement, LONG nSize);
protected:
TElementType * m_aElement;
LONG m_nSize;
};
template<typename TElementType> CArray< TElementType >::CArray(TElementType * aElement, LONG nSize) //复制C++系统数组的构造函数
{
if(aElement == NULL)
{
m_aElement = NULL;
m_nSize = 0;
}
else
{
m_aElement = new TElementType[ nSize ];
for(int i=0; i<nSize; i++)
m_aElement[ i ] = aElement[ i ]; //这里编译出错,由于模板实例化时传入的是CArray<const int>类型,operator =()操作无法执行,如何构造、复制元素为const类型的数组成为很大的问题。
}
}
问题点数:100、回复次数:18Top
1 楼qhfu(改个名字)回复于 2005-05-29 21:39:36 得分 1
基本上是无解, const变量只能在初始化列表中初始化。在这里赋值已经做了第二次了,所以 重复对const对象赋值。Top
2 楼sinkinglife(沉沦)回复于 2005-05-29 21:44:13 得分 1
不好办,没有想到好办法!
Top
3 楼defyer007(深入浅出)回复于 2005-05-30 02:06:01 得分 5
template<typename TElementType> CArray< TElementType >::CArray(TElementType * aElement, LONG nSize):m_aElement=aElement //复制C++系统数组的构造函数
{
if(aElement == NULL)
{
//m_aElement = NULL;
m_nSize = 0;
}
或者将m_aElement设为指向指针的指针:
TElementType **m_aElemnet;
再指向aElemnet
不知道行不行Top
4 楼useresu(俗人)(灌水是我无言的抗议)回复于 2005-05-30 07:47:54 得分 2
个人意见:
把数组声明为static const
这样就不用复制了Top
5 楼majcos(千里之行,始于足下)回复于 2005-05-30 09:06:14 得分 76
使用定位new操作符,在VC++2005上可以实现。程序如下(增加了一个构造函数)
#include <iostream>
using namespace std;
template<class TElementType>
class CArray //数组类
{
public:
CArray(TElementType* aElement, long nSize);
CArray(TElementType* aElement, long nSize, int typeSize);
public:
TElementType* m_aElement;
long m_nSize;
};
template<typename TElementType>
CArray< TElementType >::CArray(TElementType * aElement, long nSize) //复制C++系统数组的构造函数
{
if(aElement == NULL)
{
m_aElement = NULL;
m_nSize = 0;
}
else
{
m_aElement = new TElementType[ nSize ];
for(int i=0; i<nSize; i++)
m_aElement[ i ] = aElement[ i ]; //这里编译出错,由于模板实例化时传入的是CArray<const int>类型,operator =()操作无法执行,如何构造、复制元素为const类型的数组成为很大的问题。
}
}
template<typename TElementType>
CArray< TElementType >::CArray(TElementType* aElement, long nSize, int typeSize)
{
if(aElement == NULL)
{
m_aElement = NULL;
m_nSize = 0;
}
else
{
char* p = new char[nSize*typeSize];
memcpy(p,aElement,nSize*typeSize);
m_aElement = new (p) TElementType[ nSize ];//使用定位new
}
}
void main(){
int x[100];
for(int i=0; i<100; i++)
x[i] = i;
CArray<const int> a(x,100,sizeof(const int));
for(int i=0; i<100; i++)
cout<<a.m_aElement[i]<<" "<<endl;
system("pause");
}Top
6 楼majcos(千里之行,始于足下)回复于 2005-05-30 09:13:53 得分 1
不知道在其他编译器上能编译通过不,C++primer上有这样一段话:
我们不能在空闲存储区内创建内置类型元素的const 数组一个简单的原因是我们不
能初始化用new 表达式创建的内置类型数组的元素所有在空闲存储区内被创建的const 对
象都必须被初始化而且因为const 数组不能被初始化除了类数组所以试图用new
表达式创建一个内置类型的const 数组会导致编译错误
const int *pci = new const int[100]; // 错误
但是这条语句在VC2005上是没有编译错误的,所以我上面的程序能够正常运行。Top
7 楼darkstar21cn(≮天残≯无畏)(死亡进行时)回复于 2005-05-30 09:39:44 得分 5
把CArray(TElementType * aElement, long nSize) 改成CArray(TElementType const* aElement, long nSize)Top
8 楼stkane(左手无名指)回复于 2005-05-30 10:04:42 得分 5
我偷偷地告诉你一个operator一定管用,你要给我满分哦
答案是const_cast,你可能需要启用RTTI来鉴别什么时候需要用这个转换。详细的资料建议你查查C++ Primer 3rd editionTop
9 楼lonelyforest(一生所爱)回复于 2005-05-30 10:25:02 得分 1
同意楼上的观点,必要是就用显式转换了!Top
10 楼guyaguya(我只愿面朝大海,春暖花开)回复于 2005-05-30 11:11:46 得分 1
声明为const就是不想对成员进行修改
想要修改就不要声明为const了吧Top
11 楼hai_feng(海风)回复于 2005-05-30 13:05:04 得分 0
to stkane(左手无名指)
我偷偷地告诉你一个operator一定管用,你要给我满分哦
答案是const_cast,你可能需要启用RTTI来鉴别什么时候需要用这个转换。详细的资料建议你查查C++ Primer 3rd edition
---------------------
好像还是不行:
CArray< TElementType >::CArray(TElementType * aElement, long nSize) //复制C++系统数组的构造函数
{
if(aElement == NULL)
{
m_aElement = NULL;
m_nSize = 0;
}
else
{
m_aElement = new TElementType[ nSize ];
for(int i=0; i<nSize; i++)
const_cast<TElementType *>( m_aElement )[ i ] = aElement[ i ]; //同样是编译出错,我猜const_cast是对指针或引用抛去const,但不是对类型抛去const,所以还是要明确写出类型的,而TElementType这个在模板中复合了的类型就无法拆分了。
}
}Top
12 楼hai_feng(海风)回复于 2005-05-30 13:09:41 得分 0
to majcos(千里之行,始于足下)
你使用的是直接内存复制的办法,这个我也想到过,但是现在用的是c++而不是c,如果在c语言你的是很好的办法,但c++语言多了个在内存空间上的构造函数,你这样就没有为每个数组元素调用构造函数了,在c++是错误的。Top
13 楼hai_feng(海风)回复于 2005-05-30 13:21:19 得分 0
darkstar21cn(爱上小猫的小狗)(读不懂爱情所以来读程序)
把CArray(TElementType * aElement, long nSize) 改成CArray(TElementType const* aElement, long nSize)
不行!无论把const放在那个位置都试过都不行,这样充其量只是为指针加多一个const修饰,你不是要我利用编译器可能潜在的bug吧?Top
14 楼mostideal(三甲)回复于 2005-05-30 13:33:29 得分 1
这问题好像很难,我暂时是想不出办法。等高手来继续。。Top
15 楼hai_feng(海风)回复于 2005-05-30 14:00:24 得分 0
to majcos(千里之行,始于足下)
你在同一个位置 char* p new了2次,那么应该调用多少次delete?Top
16 楼hai_feng(海风)回复于 2005-05-30 14:03:59 得分 0
我已经想到办法了,多谢majcos(千里之行,始于足下)的启发,只要逐一对每个数组元素使用定位new即可,new时可以调用构造函数用于复制,但是具体代码我还没有写出来,如果有人比我更快贴出来,分数当然最高了。Top
17 楼hai_feng(海风)回复于 2005-05-30 14:05:08 得分 0
只要逐一对每个数组元素使用定位new即可,new时可以调用构造函数用于复制
-------
但这样怎么调用delete呢?是否可以一次过delete?Top
18 楼whyglinux(山青水秀)回复于 2005-05-30 14:24:50 得分 1
>> 当数组元素为const类型时却出现了operator =()调用时的左值问题,如何解决这个问题?
一个简单的解决方法是要求你在定义对象的时候要把元素类型设置为int( CArray<int>),而不是const int( CArray<const int>)。注意:在定义模板类对象的时候模板参数是由用户指定的,而不是由编译器推导出来的。
但是,这样的话你的程序要做出必要的调整:
一是不要把初始化使用的数组的类型和CArray的元素的类型进行关联,即用来初始化的数组类型可以和CArray的元素的类型不一致,只要存在着默认的类型转换。
二是为了可以使用const数组进行初始化,在构造函数中应该使用 const 指针。
即对构造函数修改如下:
template<class TElementType>
class CArray
{
public:
//CArray(TElementType* aElement, long nSize);
template<typename TInitArrayType>
CArray(const TInitArrayType* aElement, long nSize);
// ...Top




