[求助]复制初始化、三目运算符、返回非引用函数的return

yxluojiecpp 2015-11-19 10:01:33
各位大侠:
大家好。我一边《Visual_C++2010入门经典_第5版(中文版)》,看到了第8.6 类模板,一边实操(vs2010)。结合《C++ Primer 第4版(中文版)》中的2句话,有些疑问,麻烦各位大侠解析,谢谢。

1.复制初始化总是调用复制构造函数。
2.当形参或返回值为类类型时,由复制构造函数进行复制。

CBox类代码如下:

#ifndef CBOX_H
#define CBOX_H
#include <iostream>
using std::cout;
using std::endl;

class CBox
{
static int objectCount;
public:
// constructor
CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):m_Height(hv)
{
objectCount++;
m_Length = lv > wv ? lv : wv;
m_Width = wv < lv ? wv : lv;
cout << "CBox Constructor called." << ":\t " << objectCount << endl;
}

// copy constructor
CBox(const CBox& cpy):
m_Length(cpy.m_Length), m_Width(cpy.m_Width), m_Height(cpy.m_Height)
{
++objectCount;
cout << "CBox copy constructor called."
<< ":\t " << objectCount << endl;
}

// assignment operator function
CBox& operator=(const CBox& rhs)
{
cout << "CBox assignment operator function called." << endl;
if(this == &rhs)
return *this;
m_Length = rhs.m_Length;
m_Width = rhs.m_Width;
m_Height = rhs.m_Height;
return *this;
}

// destructor
~CBox()
{
objectCount--;
cout << "CBox Destructor called." << " :\t" << objectCount << endl;
}

public:
double Volume() const
{ return m_Length * m_Width * m_Height; }

public:
bool operator>(const CBox&) const;
bool operator>(const double&) const;
CBox operator+(const CBox& rhs) const
{
return CBox(m_Length > rhs.m_Length ? m_Length : rhs.m_Length,
m_Width > rhs.m_Width ? m_Width : rhs.m_Width,
m_Height + rhs.m_Height);
}

private:
double m_Length;
double m_Width;
double m_Height;
};

int CBox::objectCount = 0;

inline bool CBox::operator>(const CBox& rhs) const
{ return Volume() > rhs.Volume(); }

inline bool CBox::operator>(const double& value) const
{ return Volume() > value; }

inline bool operator>(const double& value, const CBox& rhs)
{ return value > rhs.Volume(); }

#endif


CSamples类模板代码如下:

#ifndef CSAMPLES_H
#define CSAMPLES_H
template<class T>
class CSamples
{
public:
// constructor
CSamples(const T values[], int count);
CSamples(const T& value);
CSamples(): m_Free(0)
{
//m_Free = 0;
cout << "CSamples default constructor called." << endl;
}

// destructor
~CSamples() { cout << "CSamples destructor called." << endl; }

public:
bool Add(const T& value);
T Max() const;

private:
T m_Values[5];
int m_Free;
};

template<class T> CSamples<T>::CSamples(const T values[], int count)
{
cout << "CSamples(2) constructor called." << endl;
m_Free = count < 5 ? count : 5;
for(int i = 0; i < m_Free; ++i)
m_Values[i] = values[i];
}

template<class T>
CSamples<T>::CSamples(const T& value)
{
cout << "CSamples(1) constructor called." << endl;
m_Values[0] = value;
m_Free = 1;
}

template<class T> bool CSamples<T>::Add(const T& value)
{
bool OK = m_Free < 5;
if(OK)
m_Values[m_Free++] = value;
return OK;
}

template<class T> T CSamples<T>::Max() const
{
// error C2446: “:”: 没有从“int”到“const CBox”的转换
// 如果CBox构造函数定义为explicit时,70行会出现上面的编译错误,
// int代表是什么?const CBox代表那个?
T theMax = m_Free ? m_Values[0] : 0;
for(int i = 1; i < m_Free; ++i)
if(m_Values[i] > theMax)
theMax = m_Values[i];
return theMax;
}
#endif


main程序代码如下:

#include "CBox.h"
#include "CSamples.h"

int main(void)
{
CBox boxes[] = { CBox(4.0, 5.0, 2.0), CBox(8.0, 5.0, 3.0), CBox(2.0, 3.0, 4.0) };
cout << endl;
CSamples<CBox> myboxes(boxes, sizeof boxes / sizeof CBox);
cout << endl;
CBox maxbox = myboxes.Max();

system("pause");
return 0;
}


输出如下:
1. CBox Constructor called.
2. CBox Constructor called.
...
8. CBox Constructor called.
9. CSamples(2) constructor called.
10. CBox assignment operator function called.
11. CBox assignment operator function called.
12. CBox assignment operator function called.

13. CBox copy constructor called. 这条代码对应Max函数中第1条代码:T theMax = m_Free ? m_Values[0] : 0; 展开后是CBox theMax =CBox(4.0, 5.0, 2.0)。问题1. 为什么13这里是调用复制构造函数,而不是调用构造函数创建CBox(4.0, 5.0, 2.0)这个临时对象?我是不是理解错误了?是不是跟m_Free ? m_Values[0] : 0; 这个三目计算符有关呢?麻烦各位大侠解析一下,非常感谢!
14. CBox copy constructor called.
15. CBox Destructor called.
16. CBox assignment operator function called.
17. CBox copy constructor called.
18. CBox Destructor called.
...全文
166 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yxluojiecpp 2015-11-20
  • 打赏
  • 举报
回复
[/quote] 我个人认为应该是三目运算符由于m_Free不能在编译期确定执行哪个,选择的m_Values[0]与0不同,所以产生了一个临时对象 写成:T theMax = m_Free ? m_Values[0] : m_Values[1]; 则不会产生这个临时对象 [/quote] 谢谢版主。我再提个问题,麻烦你了,谢谢。 问题3. 17. CBox copy constructor called.这条输出究竟是谁调用的?Max函数中最后一条代码return theMax;return语句会返回theMax的副本,在这个过程中会不会调用复制构造函数来创建这个副本,这是我最大的疑问,还是我理解错了?因为接下来CBox maxBox = myBoxes.Max();是复制初始化,它必然调用复制构造函数创建maxBox这个对象。这样一来不是得有2个复制构造函数的输出,可这里为什么只有17这一条输出呢?
paschen 版主 2015-11-19
  • 打赏
  • 举报
回复
和三目没关系 CBox c = CBox(1,2,3)调用的就是复制构造函数,因为是在初始化 而 CBox c; c = CBox(1, 2, 3) 这样第二句才是调用赋值
fefe82 2015-11-19
  • 打赏
  • 举报
回复
CBox(4.0, 5.0, 2.0) 的构造在 1, 通过 10 赋值给 m_Value[0] ,通过 13 将 m_Value[0] (不是 CBox(4.0, 5.0, 2.0) )拷贝给 theMax 。
paschen 版主 2015-11-19
  • 打赏
  • 举报
回复
引用 6 楼 yxluojiecpp 的回复:
[quote=引用 2 楼 paschen 的回复:] 和三目没关系 CBox c = CBox(1,2,3)调用的就是复制构造函数,因为是在初始化 而 CBox c; c = CBox(1, 2, 3) 这样第二句才是调用赋值
谢谢版主。你的这种解答我之前有想到过,可是接下来的14.15.输出又让我凌乱了.... 第2问题: 14. CBox copy constructor called. 15. CBox Destructor called. 这2条输出又是对应Max函数里那条代码,麻烦版主给解析一下,非常感谢。[/quote] 我个人认为应该是三目运算符由于m_Free不能在编译期确定执行哪个,选择的m_Values[0]与0不同,所以产生了一个临时对象 写成:T theMax = m_Free ? m_Values[0] : m_Values[1]; 则不会产生这个临时对象
yxluojiecpp 2015-11-19
  • 打赏
  • 举报
回复
引用 2 楼 paschen 的回复:
和三目没关系 CBox c = CBox(1,2,3)调用的就是复制构造函数,因为是在初始化 而 CBox c; c = CBox(1, 2, 3) 这样第二句才是调用赋值
谢谢版主。你的这种解答我之前有想到过,可是接下来的14.15.输出又让我凌乱了.... 第2问题: 14. CBox copy constructor called. 15. CBox Destructor called. 这2条输出又是对应Max函数里那条代码,麻烦版主给解析一下,非常感谢。
yxluojiecpp 2015-11-19
  • 打赏
  • 举报
回复
引用 1 楼 fefe82 的回复:
CBox(4.0, 5.0, 2.0) 的构造在 1, 通过 10 赋值给 m_Value[0] ,通过 13 将 m_Value[0] (不是 CBox(4.0, 5.0, 2.0) )拷贝给 theMax 。
谢谢。你说的我之前也有想过,展开代码是: CBox theMax = m_Values[0],这一句是复制初始化,总是调用复制构造函数,这样跟书上说的一致。我理解你的解答了,CBox(4.0, 5.0, 2.0)已经在1构造了,看了是我想多了。可是又凌乱了...... 第2问题了: 14. CBox copy constructor called. 15. CBox Destructor called. 这2条输出又是对应Max函数里那条代码,麻烦大侠结解析一下,非常感谢。
paschen 版主 2015-11-19
  • 打赏
  • 举报
回复
ri_aje 2015-11-19
  • 打赏
  • 举报
回复
T t = expression; 的形式叫复制构造,标准要求调用复制构造函数,同时允许优化取消对该复制构造函数的调用,但语义限制还是要满足的。

64,654

社区成员

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

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