4

假设我有:

class A
{
    A(A& foo){ ..... }
    A& operator=(const A& p) {  }
}

...
A lol;
...

A wow(...)
{

    return lol;
}

...
...
A stick;
stick = wow(...);

然后我会在最后一行得到一个编译错误。但是如果我在'A&'之前添加'const',就可以了。

我想知道为什么。问题究竟出在哪里?我不明白为什么它应该是 const。

语言:C++

我编辑了......我认为改变它是相关的。这给出了错误。

4

5 回答 5

1

以下代码在Comeau和 VC9上都能完美编译:

class A
{
public:
    A() {}
    A(A&){}
};

A lol;

A wow()
{
    return lol;
}

int main()
{
    A stick;
    stick = wow();
    return 0;
}

如果这不能用你的编译器编译,那么我怀疑你的编译器被破坏了。如果是这样,那么这意味着您应该粘贴真实代码,而不是提供与您看到的问题不相似的代码段。

于 2010-04-25T07:54:56.030 回答
1

调用wow产生一个临时对象,一个 r 值。R 值不能分配给非常量引用。由于您的复制构造函数接受非常量引用,因此您不能将调用结果wow直接传递给它。这就是为什么添加const修复问题的原因。现在复制构造函数接受 const 引用,r 值绑定到就好了。

很有可能,您的复制构造函数不会更改它正在复制的对象,因此参数应该通过 const-reference 传递。这就是复制构造函数的工作方式,除非在特定的、记录在案的情况下。

但正如 sbi 在他的回答中指出的那样,这个复制构造函数根本不应该被调用。因此,尽管这一切都是正确的,但它可能与您的问题无关。除非存在编译器错误。A stick; stick = wow();也许您的编译器看到了两步构造,并决定通过转换为来切断中间人,A stick = wow(); 但这将是一个错误,正如它从完全合法的代码中产生编译错误的事实所证明的那样。但是如果没有实际的代码,就不可能说出真正发生的事情。在您的复制构造函数出现任何问题之前,应该还有其他几个错误。

于 2010-04-25T08:14:25.700 回答
1

我相信您提到的问题类似于:

c++,匿名(未命名)变量的对象生命周期

其中的要点是,在 C++ 中,匿名临时对象不能通过引用传递,而只能通过 const 引用传递。

于 2010-04-25T08:14:49.933 回答
0

不可重现。您是否缺少默认构造函数,或者忘记创建构造函数public

请参阅http://www.ideone.com/nPsHj

(请注意,复制构造函数可以采用cv A&任何 const-volatile 组合加上一些默认参数的参数。请参阅 C++ 标准中的 §[class.copy]/2。)


编辑:有趣,g++-4.3(ideone)和 4.5(带-pedantic标志)没有编译错误,但 g++-4.2 确实抱怨:

x.cpp: In function ‘int main()’:
x.cpp:19: error: no matching function for call to ‘A::A(A)’
x.cpp:7: note: candidates are: A::A(A&)
于 2010-04-25T07:50:43.620 回答
0

这个功能:

A wow(...) 
{  ... }

按值返回一个对象。
这意味着它被复制回调用函数的位置。

这一行:

stick = wow(...);  

在棍子上进行复制构造。
复制到stick的值是从函数wow()复制回来的值。
但请记住,调用 wow() 的结果是一个临时对象(它是从 wow() 复制回来的,但尚未在变量中)。

所以现在我们看一下 A 的复制构造函数:

A(A& foo){ ..... }

您正在尝试将临时对象传递给引用参数。这是不允许的。临时对象只能绑定到 const 引用。该问题有两种解决方案:

1) 使用 const 引用。
2) 将值传递给复制构造函数。

不幸的是,如果你使用解决方案 (2),你会因为它变成一个循环依赖而有点卡住。按值传递涉及使用复制构造函数,因此您进入了一个无限循环。因此,您的解决方案是使用通过 const 引用传递。

于 2010-04-25T08:19:10.523 回答