avatar
一道c++的考古题# Programming - 葵花宝典
M*q
1
以前看到的,现在找不到了,大家给看看
int c1=0, c2=0, c3=0;
class A
{
public:
A() { c1++; }
A(const A&) { c2++; }
~A() { c3++; }
};
const A foo(const A c)
{
A ab= A(c);
return ab;
}
void main()
{
A a;
A d =foo(a);
cout << c1 << " " << c2 << " " << c3 << endl;
}
我在gcc上编译运行了一下,输出是 1 2 1
很难理解怎么答案是这个.哪位能解释一下吗?
avatar
h*o
2
which one you don't understand?

【在 M******q 的大作中提到】
: 以前看到的,现在找不到了,大家给看看
: int c1=0, c2=0, c3=0;
: class A
: {
: public:
: A() { c1++; }
: A(const A&) { c2++; }
: ~A() { c3++; }
: };
: const A foo(const A c)

avatar
M*q
3
how come copy constructor is called only twice?

【在 h**o 的大作中提到】
: which one you don't understand?
avatar
P*e
4
1 3 2 is correct

以前看到的,现在找不到了,大家给看看
int c1=0, c2=0, c3=0;
class A
{
public:
A() { c1++; }
A(const A&) { c2++; }
~A() { c3++; }
};
const A foo(const A c) //(c2=1)
{
A ab= A(c);//(c2=2)
return ab; //(c3=1)
}
void main()
{
A a; //(c1=1)
A d =foo(a); //(c2=3)
//(c3=2)
cout << c1 << " " << c2 << " " << c3 << endl;
}
我在gcc上编译运行了一下,输出是 1 2 1
很难理解怎么答案是这个.哪位能解释一下吗?

【在 M******q 的大作中提到】
: 以前看到的,现在找不到了,大家给看看
: int c1=0, c2=0, c3=0;
: class A
: {
: public:
: A() { c1++; }
: A(const A&) { c2++; }
: ~A() { c3++; }
: };
: const A foo(const A c)

avatar
M*q
5
I tried it on [email protected] Linux. The output is 1 2 1. Unless it's compiler-
dependent.

【在 P********e 的大作中提到】
: 1 3 2 is correct
:
: 以前看到的,现在找不到了,大家给看看
: int c1=0, c2=0, c3=0;
: class A
: {
: public:
: A() { c1++; }
: A(const A&) { c2++; }
: ~A() { c3++; }

avatar
P*e
6
gcc又不是standard,c++标准不是1,2,1

【在 M******q 的大作中提到】
: I tried it on [email protected] Linux. The output is 1 2 1. Unless it's compiler-
: dependent.

avatar
h*o
7
oops, i misread the problem. result from vs2008 is 1 3 2, which makes sense.

【在 M******q 的大作中提到】
: 以前看到的,现在找不到了,大家给看看
: int c1=0, c2=0, c3=0;
: class A
: {
: public:
: A() { c1++; }
: A(const A&) { c2++; }
: ~A() { c3++; }
: };
: const A foo(const A c)

avatar
M*q
8
you are saying gcc doesn't follow c++ standard?
hard to believe.

【在 P********e 的大作中提到】
: gcc又不是standard,c++标准不是1,2,1
avatar
h*o
9
i got 121 on gcc too
it seems that A ab is never created.

【在 M******q 的大作中提到】
: you are saying gcc doesn't follow c++ standard?
: hard to believe.

avatar
P*e
10
run this on g++
#include "stdio.h"
#include
int main()
{
int i=2;
if( -10*abs (i-1) == 10*abs(i-1) )
printf ("OMG,-10==10 in linux!\n");
else
printf ("nothing special here\n");
return 0;
}

【在 M******q 的大作中提到】
: you are saying gcc doesn't follow c++ standard?
: hard to believe.

avatar
X*r
11
Both (1,2,1) and (1,3,2) are correct according to the C++ standard. The
implementation is free to choose whether or not to use a temporary object
here.
See 12.2 Temporary objects [class.temporary], (2)
avatar
M*q
12
Even the output is 1 3 2, my question is
A ab= A(c) and A d =foo(a) don't call copy constructor?

sense.

【在 h**o 的大作中提到】
: oops, i misread the problem. result from vs2008 is 1 3 2, which makes sense.
avatar
M*q
13
Thanks. This is really helpful.

【在 X****r 的大作中提到】
: Both (1,2,1) and (1,3,2) are correct according to the C++ standard. The
: implementation is free to choose whether or not to use a temporary object
: here.
: See 12.2 Temporary objects [class.temporary], (2)

avatar
t*t
14
你C++标准读得不够准确

【在 P********e 的大作中提到】
: gcc又不是standard,c++标准不是1,2,1
avatar
P*e
15
ok, anyhow, gcc does not mean more c++ standard, nor MSVC
I'll stick with my temp obj

【在 t****t 的大作中提到】
: 你C++标准读得不够准确
avatar
r*r
16
a little modification to keep tracking of the copy constructor:
class A
{
public:
int x;
A() :x(0) { c1++; }
A(const A& y) : x(y.x+1) { c2++; }
};
by checking the data member "x", you can find out whether "d" and "ab" are the same object.
avatar
t*t
17
Usually, g++ DOES mean more c++ standard. At least more c++ standard than
MSVC. Although g++'s performance is not as good.

【在 P********e 的大作中提到】
: ok, anyhow, gcc does not mean more c++ standard, nor MSVC
: I'll stick with my temp obj

avatar
t*t
18
今天我有点无聊, 就说说这个temp object的事情
如果完全不优化, 实际上这个程序的结果应该是
1 5 4
可以用g++ -fno-elide-constructors 得到这个结果.
调用的顺序是
A::A(&a); // A a
A::A(&c, a); // foo(a) (1)
A::A(&temp1, c); // A(c) (2)
A::A(&ab, temp1); // A ab=... (3)
A::A(&temp2, ab); // return ab (4)
A::A(&d, temp2); // A d=.... (5)
dtor就省掉了.
这5个里面, (1)和(5)是不能省的, 这两个都不是temp object.
1 3 2的结果是把两个temp object省了.
1 2 1的结果是把(3)也省了, 这个叫做named return value optimization. VC8事实上
有这个功能,如果你用release编译,那结果就是1 2 1.
标准是这样写的

【在 P********e 的大作中提到】
: ok, anyhow, gcc does not mean more c++ standard, nor MSVC
: I'll stick with my temp obj

avatar
h*o
19
学习了

【在 t****t 的大作中提到】
: 今天我有点无聊, 就说说这个temp object的事情
: 如果完全不优化, 实际上这个程序的结果应该是
: 1 5 4
: 可以用g++ -fno-elide-constructors 得到这个结果.
: 调用的顺序是
: A::A(&a); // A a
: A::A(&c, a); // foo(a) (1)
: A::A(&temp1, c); // A(c) (2)
: A::A(&ab, temp1); // A ab=... (3)
: A::A(&temp2, ab); // return ab (4)

avatar
d*d
20
一个小问题,如果是named return value optimization,是不是该在foo里面写
return A(c);
而就不用ab了呢?

【在 t****t 的大作中提到】
: 今天我有点无聊, 就说说这个temp object的事情
: 如果完全不优化, 实际上这个程序的结果应该是
: 1 5 4
: 可以用g++ -fno-elide-constructors 得到这个结果.
: 调用的顺序是
: A::A(&a); // A a
: A::A(&c, a); // foo(a) (1)
: A::A(&temp1, c); // A(c) (2)
: A::A(&ab, temp1); // A ab=... (3)
: A::A(&temp2, ab); // return ab (4)

avatar
t*t
21
return A(c)就不是named RVO了
name的意思就是一个有名字的(局部变量)

【在 d*******d 的大作中提到】
: 一个小问题,如果是named return value optimization,是不是该在foo里面写
: return A(c);
: 而就不用ab了呢?

avatar
r*r
22
同学们这么认真读standard? //佩服
phone interview 被问过类似的问题, 数一下有一个string 的ctor 被调用. 当时凭直
觉答的.
avatar
t*t
23
我比较喜欢卖弄, 我C++都是跟Xentar学的
avatar
j*k
24
最后一句话是什么意思?指一本书?还是jhq?

【在 X****r 的大作中提到】
: Both (1,2,1) and (1,3,2) are correct according to the C++ standard. The
: implementation is free to choose whether or not to use a temporary object
: here.
: See 12.2 Temporary objects [class.temporary], (2)

avatar
j*k
25
return ab的时候,也应该有copy ctor呀

【在 P********e 的大作中提到】
: 1 3 2 is correct
:
: 以前看到的,现在找不到了,大家给看看
: int c1=0, c2=0, c3=0;
: class A
: {
: public:
: A() { c1++; }
: A(const A&) { c2++; }
: ~A() { c3++; }

avatar
P*e
26
我FT,标准什么时候说,(3)可以省了?
你帖的,第一句,(2)可以省略,第二句话(4)可以省略
ab is a variable, without (3), it's un_initialized local variable, which
doesnot make sense to me.

今天我有点无聊, 就说说这个temp object的事情
如果完全不优化, 实际上这个程序的结果应该是
1 5 4
可以用g++ -fno-elide-constructors 得到这个结果.
调用的顺序是
A::A(&a); // A a
A::A(&c, a); // foo(a) (1)
A::A(&temp1, c); // A(c) (2)
A::A(&ab, temp1); // A ab=... (3)
A::A(&temp2, ab); // return ab (4)
A::A(&d, temp2); // A d=.... (5)
dtor就省掉了.
这5个里面, (1)和(5)是不能省的,

【在 t****t 的大作中提到】
: 今天我有点无聊, 就说说这个temp object的事情
: 如果完全不优化, 实际上这个程序的结果应该是
: 1 5 4
: 可以用g++ -fno-elide-constructors 得到这个结果.
: 调用的顺序是
: A::A(&a); // A a
: A::A(&c, a); // foo(a) (1)
: A::A(&temp1, c); // A(c) (2)
: A::A(&ab, temp1); // A ab=... (3)
: A::A(&temp2, ab); // return ab (4)

avatar
t*t
27
所以我说有点歧义.
下面有个例子. 最后那两句注释应该是允许把t拿掉的意思.
[Example:
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};
Thing f() {
Thing t;
return t;
}
Thing t2 = f();
Here t does not need to be copied when returning from f. The return
value of f may be constructed directly into the object t2. ]

【在 P********e 的大作中提到】
: 我FT,标准什么时候说,(3)可以省了?
: 你帖的,第一句,(2)可以省略,第二句话(4)可以省略
: ab is a variable, without (3), it's un_initialized local variable, which
: doesnot make sense to me.
:
: 今天我有点无聊, 就说说这个temp object的事情
: 如果完全不优化, 实际上这个程序的结果应该是
: 1 5 4
: 可以用g++ -fno-elide-constructors 得到这个结果.
: 调用的顺序是

avatar
P*e
28
你没理解我意思,按照我的理解1,2,1的结果不是standard,当然你们说
implementation dependent. 反正,你们没法解释我下面的
Thing f(const Thing& p)
{
Thing c = Thing(p);
//////问题在这里,这个c,你要不要调用copy ctor来构件
//////很明显,你们说1,2,1的,根本没构件c, 明显不符合C++语法

return c;
}

【在 t****t 的大作中提到】
: 所以我说有点歧义.
: 下面有个例子. 最后那两句注释应该是允许把t拿掉的意思.
: [Example:
: class Thing {
: public:
: Thing();
: ~Thing();
: Thing(const Thing&);
: Thing operator=(const Thing&);
: void fun();

avatar
t*t
29
什么叫不符合C++语法啊,standard上说了可以省掉,就是C++语法了

【在 P********e 的大作中提到】
: 你没理解我意思,按照我的理解1,2,1的结果不是standard,当然你们说
: implementation dependent. 反正,你们没法解释我下面的
: Thing f(const Thing& p)
: {
: Thing c = Thing(p);
: //////问题在这里,这个c,你要不要调用copy ctor来构件
: //////很明显,你们说1,2,1的,根本没构件c, 明显不符合C++语法
:
: return c;
: }

avatar
t*t
30
OK,刚才我贴的paragraph 15是从11/97的draft里来的
转一个正式版的
When certain criteria are met, an implementation is allowed to omit the copy
construction of a class object, even if the copy constructor and/or destruc
tor for the object have side effects. In such cases, the implementation trea
ts the source and target of the omitted copy operation as simply two differe
nt ways of referring to the same object, and the destruction of that object
occurs at the later of the times when the two objects
would have been de

【在 P********e 的大作中提到】
: 你没理解我意思,按照我的理解1,2,1的结果不是standard,当然你们说
: implementation dependent. 反正,你们没法解释我下面的
: Thing f(const Thing& p)
: {
: Thing c = Thing(p);
: //////问题在这里,这个c,你要不要调用copy ctor来构件
: //////很明显,你们说1,2,1的,根本没构件c, 明显不符合C++语法
:
: return c;
: }

avatar
p*o
31
this problem is already fixed. also it has nothing to do
w/ c++ standard.

【在 P********e 的大作中提到】
: run this on g++
: #include "stdio.h"
: #include
: int main()
: {
: int i=2;
: if( -10*abs (i-1) == 10*abs(i-1) )
: printf ("OMG,-10==10 in linux!\n");
: else
: printf ("nothing special here\n");

avatar
t*t
32
yeah, this is called "bug"
while silently allowing "void main()" is called "not conforming to standard"

【在 p****o 的大作中提到】
: this problem is already fixed. also it has nothing to do
: w/ c++ standard.

avatar
a*o
33
this is a perfect example why c++ sucks.
avatar
y*w
34
取决于编译器的优化程度。
这个里面应该是在你那个return ab那里。进取的compiler会改写你的代码,保守的会
多cp一次。这个技术叫做name xxx optimization来着。好久不玩c++了,记不太清楚了。
//才发现前面thrust同学已经贴了牛解了,呵呵。顺便说一下,想看怎么回事编译成汇编看一下不就知道大概compiler怎么玩的了。

sense.

【在 h**o 的大作中提到】
: oops, i misread the problem. result from vs2008 is 1 3 2, which makes sense.
avatar
r*r
35
why?

【在 a*****o 的大作中提到】
: this is a perfect example why c++ sucks.
avatar
a*o
36
C++ is underspecified. It is hard to produce portable code. It is hard to
reason about the code.

【在 r*********r 的大作中提到】
: why?
相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。