求解《深度探索C++对象模型》的2个问题

EDDGA 2013-08-13 02:07:50
1、NRV优化为什么需要copy constructor?
P68、P205和P221一再表明copy constructor是激活NRV的关键(“之一”?),可原因是什么?从P66的bar()来看,NRV后不一定调copy constructor。

2、P83的多重继承,P87描述class A的模型大概是:

class X实例(1 byte,用于在内存定位的char)
class Y实例(4 byte,char + alignment)
class Z实例(4 byte,char + alignment)
class A实例(0 byte)
alignment (3 byte)
以上合共12 byte。其中Y实例和Z实例的“因virtual base class X而配置”的大小被剔除,估计就是剔除了2个X指针。

我的疑问是,为什么要剔除Y实例和Z实例的X指针?假设有

A a;
Y& y = a;

y会不会因为缺失X指针而无法回溯X?
其实我是认为class Y和class Z不是应该保留X指针而剔除char和alignment吗?

这书高深莫测,越看越慌,请各位多多指点,谢谢。
...全文
325 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ri_aje 2013-08-17
  • 打赏
  • 举报
回复
引用 3 楼 EDDGA 的回复:
[quote=引用 1 楼 ri_aje 的回复:] nrv 需要 copy ctor 是标准要求的,c++11 12.2/1 ... Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. ... 从临时对象到返回值对象需要复制构造,所以必须有复制构造函数。 第二个问题,你先把书的版本,还有是翻译的还是原版的说清楚。以后最好也给出具体章节和段落,这样别人用不同版本复查的时候也好找。
不是很懂,《深》书P66的NRV看起来就是在避免“从临时对象到返回值对象”,然则copy constructor对NRV而言还有什么用处的?我倒不关心第1问出自哪个标准,想知道为什么定这一条标准?有网友贴出了侯先生对第1问的FAQ,他说他也不明白,真是扑朔迷离 我手头《深》是2001年5月第1版,侯捷翻译[/quote] 侯捷什么时候说的?我倒是想看看引文,麻烦发上来。 看样子你也做了些调研,还把这问题说的这么神乎其神的。我都不敢说我懂了,反着我觉得下面这个肯定是原因之一。

struct non_copyable_t
{
 non_copyable_t () = default;
 non_copyable_t (non_copyable_t const&) = delete; // no copy construction.
};
non_copyable_t even_nrv_will_fail ()
{
 return non_copyable_t{};
}
这个例子里,从优化技术上讲,nrv 几乎 100% 能够把复制构造省掉。但如果据此就不检查复制构造函数语意的话,则破坏了类作者的意图,因为 delete copy ctor 的目的就是禁止复制,为了保证正确语意,标准要求 nrv 也必须尊重 copy ctor. 另外一个原因是,如果标准允许 nrv 忽略 copy ctor 语意,那么程序行为就会很怪异。体现在,当编译器能够实施 nrv 的时候,一切看似正常;而当编译器不能执行的时候,则会出编译错误,因为此时需要调用 copy ctor,后者却不能调用。要是这样的话,估计又会有不少人要骂 c++ 了。
碼上道 2013-08-17
  • 打赏
  • 举报
回复
引用 楼主 EDDGA 的回复:
1、NRV优化为什么需要copy constructor? P68、P205和P221一再表明copy constructor是激活NRV的关键(“之一”?),可原因是什么?从P66的bar()来看,NRV后不一定调copy constructor。 2、P83的多重继承,P87描述class A的模型大概是:

class X实例(1 byte,用于在内存定位的char)
class Y实例(4 byte,char + alignment)
class Z实例(4 byte,char + alignment)
class A实例(0 byte)
alignment  (3 byte)
以上合共12 byte。其中Y实例和Z实例的“因virtual base class X而配置”的大小被剔除,估计就是剔除了2个X指针。
我的疑问是,为什么要剔除Y实例和Z实例的X指针?假设有

A a;
Y& y = a;
y会不会因为缺失X指针而无法回溯X? 其实我是认为class Y和class Z不是应该保留X指针而剔除char和alignment吗? 这书高深莫测,越看越慌,请各位多多指点,谢谢。
现在的编译器,无论有无copy ctor,如果能够NRV,那么就会NRV,跟copy ctor没有关系。而书中多次提到copy ctor有了,才有实行nrv优化,估计这是早期某个编译特定的设置。 第二个问题回去看看书,好像不是你理解的这样,并不是去掉了x指针,不然确实无法回溯的。这本书上的错误,笔误也特别多,大师写的是思想,楼主也不必要纠结,领会精神就可以了。
ri_aje 2013-08-17
  • 打赏
  • 举报
回复
引用 9 楼 EDDGA 的回复:
[quote=引用 7 楼 ri_aje 的回复:] 别猜了,你混淆了标准语意和实现细节。 从语意上说,一个支持复制行为的类是不可能没有复制构造函数的,因为复制构造函数是执行复制的。 从实现上说,bitwise copy 是编译器为你默认提供的,你可以写你自己的,也可以用默认的。但无论何种情况,都是存在复制构造函数的。不能说因为是 bitwise copy,所以就不算有复制构造函数了,然后推论 '也就没有“不破坏原copy ctor操代码的意图”的要求'。 Lippman 明显理解这一点,所以他认为必须要有复制构造函数才能够支持 nrv 优化。因为唯一一种没有复制构造函数的情况就是我在 #5 给出的例子,而恰恰是在这种情况下,nrv 就完蛋了。
你意思是可复制、又符合bitwise copy semantics的类即使没有声明copy ctor,编译器也要合成一个出来? 更正:我在#6说错了,《深》P53最上面例子没copy ctor但有ctor,代码是这样

//以下声明展现了bitwise copy semantics
class Word {
public:
  Word(const char*);
  ~Word() {delete [] str;}
  // ...
private:
  int cnt;
  char* str;
}
[/quote] 对。there is no magic。你想想啊,你不写 copy ctor,编译器再不生成一个,谁都不管,那复制是怎么进行的? 具体条件其实很繁琐,总之精神就是,在类定义符合标准认定的某些条件下,编译器自动生成 copy ctor,其行为即对所有 data member 和 base class 执行 memberwise copy construction。你说的那个 bitwise copy,只对 trivially copy constructible 类型管用,其他的不行。 建议楼主先把 c++ 基础打牢,再来读"深"这样的著作,人家深子不是白叫的。强行攻之的话,即便能够走下来,所获可能也不如打牢基础后再读来的多和深。
EDDGA 2013-08-17
  • 打赏
  • 举报
回复
引用 7 楼 ri_aje 的回复:
别猜了,你混淆了标准语意和实现细节。 从语意上说,一个支持复制行为的类是不可能没有复制构造函数的,因为复制构造函数是执行复制的。 从实现上说,bitwise copy 是编译器为你默认提供的,你可以写你自己的,也可以用默认的。但无论何种情况,都是存在复制构造函数的。不能说因为是 bitwise copy,所以就不算有复制构造函数了,然后推论 '也就没有“不破坏原copy ctor操代码的意图”的要求'。 Lippman 明显理解这一点,所以他认为必须要有复制构造函数才能够支持 nrv 优化。因为唯一一种没有复制构造函数的情况就是我在 #5 给出的例子,而恰恰是在这种情况下,nrv 就完蛋了。
你意思是可复制、又符合bitwise copy semantics的类即使没有声明copy ctor,编译器也要合成一个出来? 更正:我在#6说错了,《深》P53最上面例子没copy ctor但有ctor,代码是这样

//以下声明展现了bitwise copy semantics
class Word {
public:
  Word(const char*);
  ~Word() {delete [] str;}
  // ...
private:
  int cnt;
  char* str;
}
ri_aje 2013-08-17
  • 打赏
  • 举报
回复
引用 7 楼 ri_aje 的回复:
[quote=引用 6 楼 EDDGA 的回复:] [quote=引用 5 楼 ri_aje 的回复:] [quote=引用 3 楼 EDDGA 的回复:] [quote=引用 1 楼 ri_aje 的回复:] nrv 需要 copy ctor 是标准要求的,c++11 12.2/1 ... Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. ... 从临时对象到返回值对象需要复制构造,所以必须有复制构造函数。 第二个问题,你先把书的版本,还有是翻译的还是原版的说清楚。以后最好也给出具体章节和段落,这样别人用不同版本复查的时候也好找。
不是很懂,《深》书P66的NRV看起来就是在避免“从临时对象到返回值对象”,然则copy constructor对NRV而言还有什么用处的?我倒不关心第1问出自哪个标准,想知道为什么定这一条标准?有网友贴出了侯先生对第1问的FAQ,他说他也不明白,真是扑朔迷离 我手头《深》是2001年5月第1版,侯捷翻译[/quote] 侯捷什么时候说的?我倒是想看看引文,麻烦发上来。 看样子你也做了些调研,还把这问题说的这么神乎其神的。我都不敢说我懂了,反着我觉得下面这个肯定是原因之一。

struct non_copyable_t
{
 non_copyable_t () = default;
 non_copyable_t (non_copyable_t const&) = delete; // no copy construction.
};
non_copyable_t even_nrv_will_fail ()
{
 return non_copyable_t{};
}
这个例子里,从优化技术上讲,nrv 几乎 100% 能够把复制构造省掉。但如果据此就不检查复制构造函数语意的话,则破坏了类作者的意图,因为 delete copy ctor 的目的就是禁止复制,为了保证正确语意,标准要求 nrv 也必须尊重 copy ctor. 另外一个原因是,如果标准允许 nrv 忽略 copy ctor 语意,那么程序行为就会很怪异。体现在,当编译器能够实施 nrv 的时候,一切看似正常;而当编译器不能执行的时候,则会出编译错误,因为此时需要调用 copy ctor,后者却不能调用。要是这样的话,估计又会有不少人要骂 c++ 了。[/quote] 侯先生的原话在这里http://jjhou.boolan.com/qa-object-model.htm,靠下面的黑色字 关于copy ctor,《深》书还提及,如果某class没有copy ctor(甚至可以连ctor也没有,如P52最上面),只要它符合“bitwise copy semantics”,那么编译器无需为其合成default copy ctor(从P50来看Annotated Reference Manual也持相同观点)。——这么一来,存在一种情形:“bitwise copy semantics”的class编译前后均不存在copy ctor,也就没有“不破坏原copy ctor操代码的意图”的要求,言则copy ctor对NRV的启发行为可能还在其它方面的。 [/quote] 别猜了,你混淆了标准语意和实现细节。 从语意上说,一个支持复制行为的类是不可能没有复制构造函数的,因为复制构造函数是执行复制的。 从实现上说,bitwise copy 是编译器为你默认提供的,你可以写你自己的,也可以用默认的。但无论何种情况,都是存在复制构造函数的。不能说因为是 bitwise copy,所以就不算有复制构造函数了,然后推论 '也就没有“不破坏原copy ctor操代码的意图”的要求'。 Lippman 明显理解这一点,所以他认为必须要有复制构造函数才能够支持 nrv 优化。因为唯一一种没有复制构造函数的情况就是我在 #5 给出的例子,而恰恰是在这种情况下,nrv 就完蛋了。[/quote] 更正一下吧,#5 的例子不是唯一一类没有复制构造函数的情况,还有其他情况。但 nrv 一定要求复制构造函数存在。
ri_aje 2013-08-17
  • 打赏
  • 举报
回复
引用 6 楼 EDDGA 的回复:
[quote=引用 5 楼 ri_aje 的回复:] [quote=引用 3 楼 EDDGA 的回复:] [quote=引用 1 楼 ri_aje 的回复:] nrv 需要 copy ctor 是标准要求的,c++11 12.2/1 ... Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. ... 从临时对象到返回值对象需要复制构造,所以必须有复制构造函数。 第二个问题,你先把书的版本,还有是翻译的还是原版的说清楚。以后最好也给出具体章节和段落,这样别人用不同版本复查的时候也好找。
不是很懂,《深》书P66的NRV看起来就是在避免“从临时对象到返回值对象”,然则copy constructor对NRV而言还有什么用处的?我倒不关心第1问出自哪个标准,想知道为什么定这一条标准?有网友贴出了侯先生对第1问的FAQ,他说他也不明白,真是扑朔迷离 我手头《深》是2001年5月第1版,侯捷翻译[/quote] 侯捷什么时候说的?我倒是想看看引文,麻烦发上来。 看样子你也做了些调研,还把这问题说的这么神乎其神的。我都不敢说我懂了,反着我觉得下面这个肯定是原因之一。

struct non_copyable_t
{
 non_copyable_t () = default;
 non_copyable_t (non_copyable_t const&) = delete; // no copy construction.
};
non_copyable_t even_nrv_will_fail ()
{
 return non_copyable_t{};
}
这个例子里,从优化技术上讲,nrv 几乎 100% 能够把复制构造省掉。但如果据此就不检查复制构造函数语意的话,则破坏了类作者的意图,因为 delete copy ctor 的目的就是禁止复制,为了保证正确语意,标准要求 nrv 也必须尊重 copy ctor. 另外一个原因是,如果标准允许 nrv 忽略 copy ctor 语意,那么程序行为就会很怪异。体现在,当编译器能够实施 nrv 的时候,一切看似正常;而当编译器不能执行的时候,则会出编译错误,因为此时需要调用 copy ctor,后者却不能调用。要是这样的话,估计又会有不少人要骂 c++ 了。[/quote] 侯先生的原话在这里http://jjhou.boolan.com/qa-object-model.htm,靠下面的黑色字 关于copy ctor,《深》书还提及,如果某class没有copy ctor(甚至可以连ctor也没有,如P52最上面),只要它符合“bitwise copy semantics”,那么编译器无需为其合成default copy ctor(从P50来看Annotated Reference Manual也持相同观点)。——这么一来,存在一种情形:“bitwise copy semantics”的class编译前后均不存在copy ctor,也就没有“不破坏原copy ctor操代码的意图”的要求,言则copy ctor对NRV的启发行为可能还在其它方面的。 [/quote] 别猜了,你混淆了标准语意和实现细节。 从语意上说,一个支持复制行为的类是不可能没有复制构造函数的,因为复制构造函数是执行复制的。 从实现上说,bitwise copy 是编译器为你默认提供的,你可以写你自己的,也可以用默认的。但无论何种情况,都是存在复制构造函数的。不能说因为是 bitwise copy,所以就不算有复制构造函数了,然后推论 '也就没有“不破坏原copy ctor操代码的意图”的要求'。 Lippman 明显理解这一点,所以他认为必须要有复制构造函数才能够支持 nrv 优化。因为唯一一种没有复制构造函数的情况就是我在 #5 给出的例子,而恰恰是在这种情况下,nrv 就完蛋了。
EDDGA 2013-08-17
  • 打赏
  • 举报
回复
引用 5 楼 ri_aje 的回复:
[quote=引用 3 楼 EDDGA 的回复:] [quote=引用 1 楼 ri_aje 的回复:] nrv 需要 copy ctor 是标准要求的,c++11 12.2/1 ... Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. ... 从临时对象到返回值对象需要复制构造,所以必须有复制构造函数。 第二个问题,你先把书的版本,还有是翻译的还是原版的说清楚。以后最好也给出具体章节和段落,这样别人用不同版本复查的时候也好找。
不是很懂,《深》书P66的NRV看起来就是在避免“从临时对象到返回值对象”,然则copy constructor对NRV而言还有什么用处的?我倒不关心第1问出自哪个标准,想知道为什么定这一条标准?有网友贴出了侯先生对第1问的FAQ,他说他也不明白,真是扑朔迷离 我手头《深》是2001年5月第1版,侯捷翻译[/quote] 侯捷什么时候说的?我倒是想看看引文,麻烦发上来。 看样子你也做了些调研,还把这问题说的这么神乎其神的。我都不敢说我懂了,反着我觉得下面这个肯定是原因之一。

struct non_copyable_t
{
 non_copyable_t () = default;
 non_copyable_t (non_copyable_t const&) = delete; // no copy construction.
};
non_copyable_t even_nrv_will_fail ()
{
 return non_copyable_t{};
}
这个例子里,从优化技术上讲,nrv 几乎 100% 能够把复制构造省掉。但如果据此就不检查复制构造函数语意的话,则破坏了类作者的意图,因为 delete copy ctor 的目的就是禁止复制,为了保证正确语意,标准要求 nrv 也必须尊重 copy ctor. 另外一个原因是,如果标准允许 nrv 忽略 copy ctor 语意,那么程序行为就会很怪异。体现在,当编译器能够实施 nrv 的时候,一切看似正常;而当编译器不能执行的时候,则会出编译错误,因为此时需要调用 copy ctor,后者却不能调用。要是这样的话,估计又会有不少人要骂 c++ 了。[/quote] 侯先生的原话在这里http://jjhou.boolan.com/qa-object-model.htm,靠下面的黑色字 关于copy ctor,《深》书还提及,如果某class没有copy ctor(甚至可以连ctor也没有,如P52最上面),只要它符合“bitwise copy semantics”,那么编译器无需为其合成default copy ctor(从P50来看Annotated Reference Manual也持相同观点)。——这么一来,存在一种情形:“bitwise copy semantics”的class编译前后均不存在copy ctor,也就没有“不破坏原copy ctor操代码的意图”的要求,言则copy ctor对NRV的启发行为可能还在其它方面的。
taodm 2013-08-16
  • 打赏
  • 举报
回复
别太钻牛角尖。
貌似是没有copy ctor的优化在C语言时代就启用了,
所以NRV只是补充规定了有copy ctor这种C++才引入的情况下怎么优化。
EDDGA 2013-08-16
  • 打赏
  • 举报
回复
引用 1 楼 ri_aje 的回复:
nrv 需要 copy ctor 是标准要求的,c++11 12.2/1 ... Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. ... 从临时对象到返回值对象需要复制构造,所以必须有复制构造函数。 第二个问题,你先把书的版本,还有是翻译的还是原版的说清楚。以后最好也给出具体章节和段落,这样别人用不同版本复查的时候也好找。
不是很懂,《深》书P66的NRV看起来就是在避免“从临时对象到返回值对象”,然则copy constructor对NRV而言还有什么用处的?我倒不关心第1问出自哪个标准,想知道为什么定这一条标准?有网友贴出了侯先生对第1问的FAQ,他说他也不明白,真是扑朔迷离 我手头《深》是2001年5月第1版,侯捷翻译
逸萌 2013-08-13
  • 打赏
  • 举报
回复
ri_aje 2013-08-13
  • 打赏
  • 举报
回复
nrv 需要 copy ctor 是标准要求的,c++11 12.2/1 ... Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. ... 从临时对象到返回值对象需要复制构造,所以必须有复制构造函数。 第二个问题,你先把书的版本,还有是翻译的还是原版的说清楚。以后最好也给出具体章节和段落,这样别人用不同版本复查的时候也好找。

65,187

社区成员

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

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