类的复制构造函数这样写有问题吧?大家看看

紫色动力 2010-07-03 11:01:32
现在是一个类的复制构造函数, 我是疑问是:
a是这个类的变量,a不为空,假设函数fun()的返回值是这个类,当“a = fun() ”时,会调用复制构造函数。此时,但a不为空,下面的这个复制构造函数是不是会有问题。因为a不为空,copy这个函数没有把变量清空就直接复制了。请朋友指点下,谢谢!


template <typename T>
void linkedQueue<T>::copy(const linkedQueue<T>& q)
{
// qback moves through the list we are building and
// winds up at the rear of our new list. p
// moves through the list we are copying
node<T> *newNode, *p = q.qfront;

// initially, the list is empty
qfront = qback = NULL;

// nothing to do if p is NULL
if (p != NULL)
{
// create the first node in the queue and assign
// its addres to qback
qfront = qback = getNode(p->nodeValue);

// move forward in the list we are copying
p = p->next;

// copy remaining items
while(p != NULL)
{
// insert new node at the back
newNode = getNode(p->nodeValue);
qback->next = newNode;

// qback is the new node
qback = newNode;

// move to the next node of the list we are copying
p = p->next;
}
}

// the size of the new list is the size of q
qsize = q.qsize;
}

template <typename T>
linkedQueue<T>::linkedQueue(const linkedQueue<T>& obj)
{
// call copy() and pass the pointer to the front of
// the linked list in obj
copy(obj);
}
...全文
155 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 arong1234 的回复:]
构造函数不返回任何东西,a=fun(),调用的是operator=算子,和复制构造毫无关系

引用 3 楼 djjlove_2008 的回复:
在调用复制构造时,返回的才是void吧,但这样说又不对,复制构造函数应该返回该对象的引用才对,如果
a = fun()成立的话,那只能fun()在内部调用了copy()函数。从源代码中分析copy()函数是没有错的。
所以Copy()函数是正确的……
[/Quote]
那构造函数什么时候用到呢?
arong1234 2010-07-04
  • 打赏
  • 举报
回复
构造函数不返回任何东西,a=fun(),调用的是operator=算子,和复制构造毫无关系[Quote=引用 3 楼 djjlove_2008 的回复:]
在调用复制构造时,返回的才是void吧,但这样说又不对,复制构造函数应该返回该对象的引用才对,如果
a = fun()成立的话,那只能fun()在内部调用了copy()函数。从源代码中分析copy()函数是没有错的。
所以Copy()函数是正确的,只是他是被fun()函数调用了。
[/Quote]
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pengzhixi 的回复:]
a = fun() ;调用的是赋值运算符
[/Quote]
fun()返回的时候是会调用复制构造函数吧,而不是赋值运算符吧
wyz007134 2010-07-04
  • 打赏
  • 举报
回复
复制(拷贝)构造函数的原型是
linkedQueue<T>::linkedQueue(const linkedQueue<T>& obj)
而lz的a = fun() 调用中,所谓类的变量(还是说对象好一些!)a的值已经存在,说明a已经被构造好了,而a=很明显的是调用了“=”赋值操作,而并不是构造。
类比下:
	
int a(5); //调用构造函数
int b(a); //调用拷贝构造函数,把a的值给b
a = 6; //调用赋值“=”操作符改变a的值,至于a原来的值,不需要我们关心
cout << a;
cout << b;

再看这段代码

#include <iostream.h>
class A
{
public:
~A(){cout << "析构\n";}
A(int iValue){cout << "构造\n";value = iValue;}
int value;
};
int main()
{
A a(4);
A b(a);
a = b; //观察输出,发现调用了两次析构,就是对象a和b的析构,而屏蔽
return 0; //了a=b这个赋值语句发现仍然是两次析构,也就是说,尽管
//赋值覆盖了a原来的值,但是并没有发生析构,因为赋值只是在
//a已有的内存空间上进行成员值的“重写”罢了,并不是释放掉
//a原有的空间,而另开辟一块来存放b的成员
}
leithron 2010-07-04
  • 打赏
  • 举报
回复
试试重载=运算符
arong1234 2010-07-04
  • 打赏
  • 举报
回复
that's it!如果不是这样,那么func的返回过程不就随着是不是有a=而变化么?这显然不可能[Quote=引用 11 楼 purplepower 的回复:]
那可不可以这样理解:在执行a = fun()的时候,fun()的返回值放在一个临时变量里,这时用到复制构造函数;然后再把这个临时变量赋值给a,这时用到了运算符重载,也就是等号。我刚才试了下,好像是这样的。这样的话复制构造函数就不用考虑复制的值是否为空,肯定是给没有初始化的新变量赋值,然后再把这个值用运算符重载的等号赋值给当前变量,这时,运算符重载linkedQueue<T>& operat……
[/Quote]
P_ghost 2010-07-04
  • 打赏
  • 举报
回复
请注意,我是通过拷贝构造了一个临时对象做交换的,所以临时对象析构的时候会释放掉我原先的p_,所以是安全的。Test(rhs)拷贝构造的临时对象
枫code 2010-07-04
  • 打赏
  • 举报
回复
觉得有些模糊,我的水平有限,写的是不模板啊
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
还有一个问题你没有说:就是交换了是不是把原来的值改了?这样做是不是有问题?

[Quote=引用 14 楼 p_ghost 的回复:]
补充一点,我在operator =中少谢了return *this; 大意了,请LZ自行添加
[/Quote]
P_ghost 2010-07-04
  • 打赏
  • 举报
回复
补充一点,我在operator =中少谢了return *this; 大意了,请LZ自行添加
P_ghost 2010-07-04
  • 打赏
  • 举报
回复
std::swap在<algorithm>头中
使用swap实现operator =可以做到防止自赋值以及,甚至还是异常安全的
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
你的代码这几行看不懂:

Test& operator =(const Test& rhs)
{
Test(rhs).swap(*this);
}


为什么是交换呢?是不是把这两个指针值的内容交换了,就是把指向的地址交换了,所以值也就变了。要是这样的话不是把rhs的值给修改了吗?
Test(rhs).swap(*this)写成这样:rhs.swap(*this)可以吗?为什么还有个Test呢?

还有

void swap(Test& rhs)
{
std::swap(p_, rhs.p_);
}

这个swap是标准库中的吗?在哪个头文件里?谢谢哦,初级水平呵呵。

[Quote=引用 9 楼 p_ghost 的回复:]
LZ的“不为空”是什么意思?意思是a这个变量已经存在?如果是这样,那就不会再次构造了,也就不会调用复制构造函数,取而代之的是operator =

你应该实现operator =,在实现中首先判断是否是自赋值,如果不是,则清空自身new出来的成员,然后依据参数中的对象中的成员来new出新成员方可。或者实现一个swap,在operator =中通过swap来实现。
例如:

C/C++ c……
[/Quote]
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
那可不可以这样理解:在执行a = fun()的时候,fun()的返回值放在一个临时变量里,这时用到复制构造函数;然后再把这个临时变量赋值给a,这时用到了运算符重载,也就是等号。我刚才试了下,好像是这样的。这样的话复制构造函数就不用考虑复制的值是否为空,肯定是给没有初始化的新变量赋值,然后再把这个值用运算符重载的等号赋值给当前变量,这时,运算符重载linkedQueue<T>& operator= (const linkedQueue<T> &rhs)就需要考虑把原来变量的值清空。

[Quote=引用 10 楼 arong1234 的回复:]
我们说不用是指=部分,fun返回部分当然用,我想搂住的意思不是说fun的返回部分吧?

你已经说出了拷贝构造的所有应用,希望搂住能理解

引用 8 楼 purplepower 的回复:
引用 5 楼 arong1234 的回复:
构造函数不返回任何东西,a=fun(),调用的是operator=算子,和复制构造毫无关系


我觉得你说得不对,复制构造函数有三个功能:
1). 一……
[/Quote]
arong1234 2010-07-04
  • 打赏
  • 举报
回复
我们说不用是指=部分,fun返回部分当然用,我想搂住的意思不是说fun的返回部分吧?

你已经说出了拷贝构造的所有应用,希望搂住能理解
[Quote=引用 8 楼 purplepower 的回复:]
引用 5 楼 arong1234 的回复:
构造函数不返回任何东西,a=fun(),调用的是operator=算子,和复制构造毫无关系


我觉得你说得不对,复制构造函数有三个功能:
1). 一个对象以值传递的方式传入函数体
2). 一个对象以值传递的方式从函数返回
3). 一个对象需要通过另外一个对象进行初始化
那么“a = fun()”就用到了第2个功能。函数fun……
[/Quote]
P_ghost 2010-07-04
  • 打赏
  • 举报
回复
LZ的“不为空”是什么意思?意思是a这个变量已经存在?如果是这样,那就不会再次构造了,也就不会调用复制构造函数,取而代之的是operator =

你应该实现operator =,在实现中首先判断是否是自赋值,如果不是,则清空自身new出来的成员,然后依据参数中的对象中的成员来new出新成员方可。或者实现一个swap,在operator =中通过swap来实现。
例如:

class Test{
int* p_;
public:
Test() : p_(new int(0)){}
Test(const Test& rhs) : p_(new int(*rhs.p_)){}
Test& operator =(const Test& rhs)
{
Test(rhs).swap(*this);
}
~Test(){delete p_;}

void swap(Test& rhs)
{
std::swap(p_, rhs.p_);
}
};
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 arong1234 的回复:]
构造函数不返回任何东西,a=fun(),调用的是operator=算子,和复制构造毫无关系

[/Quote]
我觉得你说得不对,复制构造函数有三个功能:
1). 一个对象以值传递的方式传入函数体
2). 一个对象以值传递的方式从函数返回
3). 一个对象需要通过另外一个对象进行初始化
那么“a = fun()”就用到了第2个功能。函数fun()的返回值是这个类,如果是这个声明fun函数:linkedQueue<int> fun()。就应该用到了第2个功能。按照2楼的解释是能说得通的。
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
那构造函数什么时候用到呢?
紫色动力 2010-07-04
  • 打赏
  • 举报
回复
谢谢大家啦,呵呵
djjlove_2008 2010-07-03
  • 打赏
  • 举报
回复
在调用复制构造时,返回的才是void吧,但这样说又不对,复制构造函数应该返回该对象的引用才对,如果
a = fun()成立的话,那只能fun()在内部调用了copy()函数。从源代码中分析copy()函数是没有错的。
所以Copy()函数是正确的,只是他是被fun()函数调用了。
cattycat 2010-07-03
  • 打赏
  • 举报
回复
如果linkedQueue<int> a=fun()类似这样,调用考被狗仔函数。如果a已经初始化过了,则调用赋值运算符operator=.
加载更多回复(1)

64,654

社区成员

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

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