复制构造函数,为什么要按值返回函数
假设我有:
class A
{
A(A& foo){ ..... }
A& operator=(const A& p) { }
}
...
A lol;
...
A wow(...)
{
return lol;
}
...
...
A stick;
stick = wow(...);
那么我会在最后一行收到编译错误。但如果我在“A&”之前添加“const”,就可以了。
我想知道为什么。究竟问题出在哪里呢? 我不明白为什么它应该是 const。
语言:C++
我编辑过...我认为改变是相关的。这会产生错误。
Suppose i have:
class A
{
A(A& foo){ ..... }
A& operator=(const A& p) { }
}
...
A lol;
...
A wow(...)
{
return lol;
}
...
...
A stick;
stick = wow(...);
Then I'll get a compile error in the last line. But if I add 'const' before 'A&', its ok.
I want to know why. Where it's exactly the problem?
I dont get why it should be const.
Language: C++
I edited... I think that change its relevant. That gives error.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我相信您提到的问题类似于:
c++ ,匿名(未命名)变量的对象生命周期,
其中要点是在 C++ 中,匿名临时变量不能通过引用传递,而只能通过 const 引用传递。
I believe the problem you are mentioning is similar to:
c++, object life-time of anonymous (unnamed) variables
where the essential point is that in C++ anonymous-temporaries can not be passed by reference but only by const reference.
以下代码可以在 Comeau 和 VC9 上完美编译:
如果您的编译器无法编译此代码,那么我怀疑你的编译器坏了。如果确实如此,则意味着您应该粘贴真实的代码,而不是提供与您看到的问题不同的代码片段。
The following code compiles perfectly fine with both Comeau and VC9:
If this doesn't compile with your compiler, then I suspect your compiler to be broken. If it does, then that means you should have pasted the real code, instead of supplying a snippet that doesn't resemble the problem you see.
对
wow
的调用会产生一个临时对象,即右值。 R 值不能分配给非常量引用。由于您的复制构造函数接受非常量引用,因此您无法将wow
调用的结果直接传递给它。这就是为什么添加const
可以解决问题。现在,复制构造函数接受 const 引用,r 值可以很好地绑定到该引用。有可能,您的复制构造函数不会更改它正在复制的对象,因此参数应该通过常量引用传递。这就是复制构造函数的工作方式,除非在特定的、有记录的情况下。
但正如 sbi 在他的回答中指出的那样,这个复制构造函数根本不应该被调用。因此,虽然这都是真的,但它可能与您的问题无关。除非编译器有bug。也许您的编译器看到了两步构造,并决定通过转换
A Stick; 来消除中间人。 Stick = wow();
转换为A Stick = wow();
但这将是一个错误,事实证明它会在完全合法的代码中产生编译错误。但如果没有实际的代码,就不可能说出到底发生了什么。在复制构造函数出现任何问题之前,应该还存在其他几个错误。The call to
wow
results in a temporary object, an r-value. R-values can not be assigned to non-const references. Since your copy constructor accepts non-const references, you can not pass the result of the call towow
directly to it. This is why adding theconst
fixes the problem. Now the copy constructor accepts const references, which r-values bind to just fine.Chances are, your copy constructor does not change the object it is copying, so the paramter should be passed by const-reference. This is how copy constructors are expected to work, except in specific, documented circumstances.
But as sbi points out in his answer, this copy constructor shouldn't be getting called at all. So while this is all true, it likely has nothing to do with your problem. Unless there is a compiler bug. Perhaps your compiler sees the two-step construction, and decided it'll cut out the middle man by converting
A stick; stick = wow();
intoA stick = wow();
But this would be a bug, as evidenced by the fact that it produces a compile error out of perfectly legal code. But without actual code, its impossible to say what's really happening. There should be several other errors before any issues with your copy constructor come up.不可重现。您是否缺少默认构造函数,或者忘记将构造函数设为public
?请参阅 http://www.ideone.com/nPsHj。
(请注意,复制构造函数可以采用带有任何常量易失性组合的
cv A&
参数以及一些默认参数。请参阅C++中的§[class.copy]/2标准。)编辑:有趣的是,g++-4.3(ideone)和4.5(带有
-pedantic
标志)没有编译错误,但 g++-4.2 确实抱怨:Not reproducible.Are you missing the default constructor, or forgot to make the constructorspublic
?See http://www.ideone.com/nPsHj.
(Note that, a copy constructor can take an
cv A&
argument with any const-volatile combination plus some default arguments. See §[class.copy]/2 in C++ standard.)Edit: Interesting, g++-4.3 (ideone) and 4.5 (with
-pedantic
flag) don't have the compile error, but g++-4.2 do complain:该函数:
按值返回一个对象。
这意味着它被复制回调用该函数的位置。
这一行:
在棒上进行复制构造。
复制到 Stick 中的值是从函数 wow() 复制回的值。
但请记住,调用 wow() 的结果是一个临时对象(它是从 wow() 复制回来的,但尚未在变量中)。
现在我们看看 A 的复制构造函数:
您正在尝试将临时对象传递给引用参数。这是不允许的。临时对象只能绑定到 const 引用。该问题有两种解决方案:
1) 使用 const 引用。
2) 按值传递到复制构造函数。
不幸的是,如果您使用解决方案(2),您会遇到一点困难,因为它变成了循环依赖。按值传递涉及使用复制构造函数,因此您会进入无限循环。所以你的解决方案是使用 const 引用传递。
This function:
returns an object of by value.
This means it is copied back to the point where the function was called.
This line:
Does a copy construction on stick.
The value copied into stick is the value copied back from the function wow().
But remember that the result of the call to wow() is a temporary object (it was copied back from wow() but is not in a variable yet).
So now we look at the copy constructor for A:
You are trying to pass a temporary object to a reference parameter. This is not allowed. A temporary object can only be bound to a const reference. There are two solutions to the problem:
1) Use a const reference.
2) Pass by value into the copy constructor.
Unfortunately if you use solution (2) you get a bit stuck as it becomes a circular dependency. Passing by value involves using the copy constructor so you enter an infinte loop. So your solution is to use pass by const reference.