vector的使用问题

mul 2006-04-17 05:46:59
以下一段程序:
#include <vector>
using namespace std;

class resource
{
public:
resource() : _memory(0){}
virtual ~resource() {}
resource(resource& aResource)
{
_memory = aResource._memory;
aResource._memory = 0;
}
void alloc(size_t len)
{
_memory = new unsigned char[len];
}
void clear()
{
if (_memory != 0)
delete[] _memory;
_memory = 0;
}
protected:
unsigned char* _memory;
private:
};

int main(int argc, char* argv[])
{
resource res;

vector<resource> resources;
resources.push_back(res);

return 0;
}
编译失败,提示:error C2558: class“resource” : 没有可用的复制构造函数或复制构造函数声明为“explicit”。
看提示好像是需要const参数的拷贝构造函数,但我的aResource拷贝时是需要修改的,无奈,改了拷贝构造:
resource(const resource& aResource)
{
_memory = aResource._memory;

resource& ref = const_cast<resource&>(aResource);
ref._memory = 0;
}
这代码看了有点别扭,本来aResource是需要修改的,却又加了const修饰,在函数内部又去修改它。

不清楚大家是怎么解决这个问题的?
再想问一下,vector::push_back的参数为什么非要用const修饰(好像其他方法也都是这样)?
...全文
337 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
iceprince83 2006-04-19
  • 打赏
  • 举报
回复
to mul:
copy constructor设计的初衷是由一个对象来构造另外一个同类型的对象,参数设计成const的原因是保护被copy的对象不被修改,你的这种用法修改了被copy的对象,实际上已经不是纯粹意义上的“拷贝构造”了,所以会出现下面这种不是很优美的代码。
resource(const resource& aResource)
{
_memory = aResource._memory;

resource& ref = const_cast<resource&>(aResource);
ref._memory = 0;
}

建议你再仔细考虑一下,是否一定需要在拷贝构造的时候修改原来的对象。
iceprince83 2006-04-19
  • 打赏
  • 举报
回复
to jasonhc(静下心来编程):
第一个问题是我错了,我把copy assignment和copy constructor搞混了,非常感谢你帮我指出来。

对于第二个问题的解释:
因为编译器的提示是
“编译失败,提示:error C2558: class“resource” : 没有可用的复制构造函数或复制构造函数声明为“explicit”。”
所以我认为应该是编译器没有把resource(resource& aResource);函数当作copy constructor
而把const加上后,编译就通过了,

我查了书,你可以看一下<the c++ programming language> 10.2.5
原文如下:
By default,the copy of a class object is a copy of each member.If that default
is not the behavior wanted for a class X,a more appropriate behavior can be
provided by defining a copy constructor, X::X(const X&);
基于以上的原因,我仍然坚持我的观点






jasonhc 2006-04-19
  • 打赏
  • 举报
回复
另外,"第一:参数必须是const,这是copy constructor规定的,如果不是const,则编译器不把这个函数当成copy constuctor"。哪本书上有这种说法,我去找找看,谢谢。
jasonhc 2006-04-19
  • 打赏
  • 举报
回复
回复iceprince83:
你的代码有问题。这个是拷贝构造函数,被调用时对象还没有初始化,内存当然也没有分配,所以不用释放_memory指向的内存。不应该直接拷贝指针的值,应该分配内存给_memory,再把aResource的内容拷贝过来。aResource的内存也不应该释放,你这样会修改aResource的内容,这不是拷贝构造函数所要表达的意思,而且aResource已经是const了,其内容是不能被修改的。
详细情况可以参考Effective C++条款11。

------------------------------------------------------------------------------
第二:你的这个代码会造成内存泄漏
resource(const resource& aResource)
{
clear(); //如果不clear,那么修改前的 _memory 所指向的内存空间将没有指针指向
_memory = aResource._memory;
aResource.clear(); //道理如上
aResource._memory = 0;
}

mul 2006-04-19
  • 打赏
  • 举报
回复
没什么满意的答案。:)
我的例子程序只是说明有这种问题的存在,随手写的,不必太认真。
>>eplanet(小汽车):
还是那句话:函数声明和实现是同一个(或同一伙人)做的,修改不修改入参还不是他们说了算,对调用人“表达一种“声明””意义有多大,有必要对这种声明丢弃灵活性?(使用type&也可接受const type&类型)
>>iceprince83(iceprince83):'参数必须是const,这是copy constructor规定的'
呵呵,没这种规定吧。

不过可以看出mutable存在的必要性了,呵呵,再等一天看看,明天结帖。
stormsxf 2006-04-18
  • 打赏
  • 举报
回复
路过,也不明白,学习先
iceprince83 2006-04-18
  • 打赏
  • 举报
回复
谈两点我的看法和一个疑惑
第一:参数必须是const,这是copy constructor规定的,如果不是const,则编译器不把这个函数当成copy constuctor
第二:你的这个代码会造成内存泄漏
resource(const resource& aResource)
{
clear(); //如果不clear,那么修改前的 _memory 所指向的内存空间将没有指针指向
_memory = aResource._memory;
aResource.clear(); //道理如上
aResource._memory = 0;
}

疑惑:
我在执行你的代码时遇到了一个异常
是clear函数中的delete函数中的
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
没有通过,我不太明白为什么会有这个问题,请指教一下




mul 2006-04-18
  • 打赏
  • 举报
回复
谢谢两位。
加上mutable修饰可以省去const转换,但不觉得用得有点不爽?(我是说在方法内部需要修改入参,入参却又用了const修饰)
拷贝构造函数你们都写成resource(resource const& aResource),我用resource(const resource& aResource),没什么区别吧?
>> 参数为什么非要用const
我是指为什么要用const type&,比如void push_back(const _Ty& _Val),这是造成我需要使用const修饰的拷贝构造函数。为什么不直接使用type&。
eplanet 2006-04-18
  • 打赏
  • 举报
回复
所谓const就是对参数修改的一个限制,防止函数内部对参数的修改.提升整个程序数据的安全性.有点类似于private.虽然可以弃置不用,但用了会使算法的可靠性得到提升.

而用const修饰的参数多是指针或引用,因为指针和引用可以直接修改内部.但用传值调用对于较大的类或结构又会浪费内存.所以const修饰的指针或引用可以使用传地址调用,同时又保证了数据的安全性.
sharpdew 2006-04-18
  • 打赏
  • 举报
回复
既然是拷贝,当然不希望你修改被拷贝对象的值咯,如果被拷贝对象是局部变量或者临时对象,而你的容器是全局,如果这时候不强制使用const进行拷贝的话,那你的程序岂不死得很快,呵呵!
mul 2006-04-18
  • 打赏
  • 举报
回复
???
mul 2006-04-18
  • 打赏
  • 举报
回复
>>参数中的const修饰符更倾向于表达一种“声明”:这个参数不希望被修改。
没错。但是有必要对这种声明丢弃灵活性吗?(使用type&也可接受const type&类型)
另外,函数声明和实现是同一个(或同一伙人)做的,修改不修改入参还不是他们说了算,对调用人“表达一种“声明””意义有多大?
>>至于你的resource对象的拷贝构造函数,我有些不明白,为什么会在这里修改_memory成员?
看看我的类名,有些系统资源是需要这样处理的。
>>为什么不在析构函数中释放?
这样会造成资源多次释放。
cityyokel 2006-04-18
  • 打赏
  • 举报
回复
参数中的const修饰符更倾向于表达一种“声明”:这个参数不希望被修改。

至于你的resource对象的拷贝构造函数,我有些不明白,为什么会在这里修改_memory成员?

为什么不在析构函数中释放?
cunsh 2006-04-17
  • 打赏
  • 举报
回复
>> 参数为什么非要用const

用一个const T*做形参时.可以给它传递一个T * 实参. 但反过来是不行的.
cunsh 2006-04-17
  • 打赏
  • 举报
回复

resource(resource const& aResource)
{
_memory = aResource._memory;
aResource._memory = 0;
}

再改一个:

protected:
mutable unsigned char* _memory;
healer_kx 2006-04-17
  • 打赏
  • 举报
回复
问题在于你的类的拷贝构造函数

resource(resource& aResource)
{
_memory = aResource._memory;
aResource._memory = 0;
}

should be like this:
resource(resource const& aResource)
{
_memory = aResource._memory;
aResource._memory = 0;
}

65,187

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧