C++ 在这个C++;一小条
在这个问题中,我们必须找出复制构造函数被调用了多少次, 根据我的说法是5,但答案是7。这是怎么发生的C++ 在这个C++;一小条,c++,constructor,copy-constructor,C++,Constructor,Copy Constructor,在这个问题中,我们必须找出复制构造函数被调用了多少次, 根据我的说法是5,但答案是7。这是怎么发生的 Widget f(Widget u) { Widget v(u); Widget w = v; return w; } int main() { Widget x; Widget y = f(f(x)); } 在禁用复制省略和移动的情况下,有: 1) 小部件y=f(f(x)) 在f函数中有4个复制构造函数的调用 1) u按值传递 2) v是从u复制初
Widget f(Widget u)
{
Widget v(u);
Widget w = v;
return w;
}
int main()
{
Widget x;
Widget y = f(f(x));
}
在禁用复制省略和移动的情况下,有: 1) 小部件y=f(f(x))代码> 在
f
函数中有4个复制构造函数的调用
1) u
按值传递
2) v
是从u
复制初始化的
3) w
是从v
复制初始化的
4) w
在返回时复制
所以,实际上有9个电话
启用复制省略后,gcc/clang上有5个调用。+1-赋值
小部件y=f(f(x))
+2-调用函数f()
两次,通过值而不是引用传递参数。
+2-复制v(u)
调用两次
+2-复制初始化小部件w=v
调用两次
等于7
请注意,对于某些设置下的某些编译器,这是正确的。其他答案也是正确的,my解释了为什么结果可能是7,例如,您可以在bcc32
下获得
根据我的说法,一个复制构造函数被调用了多少次
答案是7。这是怎么发生的
Widget f(Widget u)
{
Widget v(u);
Widget w = v;
return w;
}
int main()
{
Widget x;
Widget y = f(f(x));
}
将代码段更新为实际工作的代码后(请参见底部),您可以看到以下输出(test.cpp中的代码):
我们只需要看看单个函数调用是如何工作的。为此,我们有:
Widget f(Widget u)
{
Widget v(u);
Widget w = v;
return w;
}
y = f(x)
在以下情况下调用复制选择器:
- 按值将
发送到x
f
- 在
中从f
创建u
v
- 将
分配到v
中w
f
- 从
f
- 将
的返回值赋值给f
y
f
的每次调用,我们需要使用copy-ctor4次,由于f
被调用两次,您已经有+8次copy-ctor调用,+1次用于y
中的最终赋值,总共9次
但是为什么我们在上面的输出中只看到5个呢?
答案是:优化
GCC正在通过优化删除一些复制操作。如果我们使用-fno-elide构造函数
标志构建它,我们可以看到所有这些:
➜ /tmp g++ -fno-elide-constructors -o -std=c++11 test test.cpp && ./test
def ctor
copy ctor
copy ctor
copy ctor
copy ctor
copy ctor
copy ctor
copy ctor
copy ctor
copy ctor
这告诉GCC不要执行我们之前构建中看到的优化,它显示了x
使用的默认构造函数下面的所有复制构造函数调用
使用的代码段
#包括
使用名称空间std;
类小部件{
公众:
Widget(){你不能在调试器中运行它并跟踪每一步吗?除此之外,请发布一个最小但完整的Widget定义。你能说出你找到了哪5个,这样我们就可以更容易地告诉你你错过了哪5个吗?(请注意,准确的数字取决于复制省略、移动语义等)每个f(x)不是只有3个吗
call+1 fory
assignment?您按值调用函数,并在函数内部进行两次复制。您按值将参数传递给函数,这样就生成了一个副本。如果您使用的函数类似于f(Widget&u)
你会得到5份副本。没问题。让我把它转化为一个答案。OP得到了7份-我假设他在静态变量中计算了这一份,或者在构造函数中计算了输出。所以我们在这里看到了复制省略。我猜这是返回期间的副本,在这里被省略了。我认为这一份缺少了函数运行时由f
创建的副本“代码”>返回< /COD>语句。这个答案似乎不正确。考虑不应该返回值优化来处理这个问题吗?阅读我的文章并具体看<代码> FNO-ELIDE构造函数< /COD>基于旗标的东西。确实,你对G++是正确的。但是答案应该是7,它在某些编译器下面。对于7,找到一个E.X.Bcc32编译器。复制了7份。这个问题不是很好,因为它没有指定环境。我同意这个问题不是很好,但是说答案“应该是7”在我看来仍然是不正确的。7是特定编译器进行一些优化的结果,但是如果我们走这条路,我们永远不会得到“正确的”回答b/c有很多不同的编译器。你需要告诉你的编译器不要优化那样的东西(就像我对g++
所做的那样),然后才能看到所有的copy-ctor调用。是的,我也有同样的问题,但我认为正如M.M.所指出的,存在一些版本问题“注意:C++03中的答案与C++11中的答案不同,除非小部件是不可移动的;您询问的是哪个版本?”@BijonGuha:使用-std=C++11
标志显示没有区别,并且是您在注释中声明使用的,那么为什么您仍然说这是“版本差异”“根据你的信息,我的帖子是准确的。是的,你是正确的。因为我只是一个初学者,所以我没有那么多想法。即使我也不知道这意味着什么”-std=c++11”。但当我在编译器中运行你的代码时,我得到了5。说真的,我也完全搞不清楚发生了什么。如果你对我在帖子中提到的事情有什么具体问题,请告诉我。落选者能否解释他/她的落选理由?
#include <iostream>
using namespace std;
class Widget {
public:
Widget() { cout << "def ctor" << endl; }
Widget(const Widget &other) { cout << "copy ctor" << endl; }
};
Widget f(Widget u)
{
Widget v(u);
Widget w = v;
return w;
}
int main()
{
Widget x;
Widget y = f(f(x));
return 0;
}