这更多的是征求意见,而不是我在代码库中遇到的特定困难。采用以下简单示例: -
class Ref
{
public:
Ref(char* s, size_t l) : _s(s), _l(l) {}
private:
char* _s;
size_t _l;
};
std::stringstream ss;
char a[256];
ss >> Ref(a, sizeof(a)); // <-------- here is the discussion line
friend std::stringstream& operator>>(std::stringstream& ss, Ref& r)
{
// perform some functionality
}
现在使用Visual Studio时,上面的编译很好......似乎弄清楚当我使用运算符&gt;&gt;时,因为我有一个覆盖,它接受一个引用,我的意思是将创建的对象传递为一个参考。但是,当使用gcc时,它会摇摆不定。它抱怨说操作没有操作员超载。
从技术上讲,我认为gcc是正确的,因为我正在创建对象并基本上将对象传递给运算符而不是对象的引用。我只是想知道为什么Microsoft编译器会允许这个,或者为什么gcc无法弄清楚我打算通过引用传递它?在上面的例子中,Ref对象相当简单,通过引用或对象本身传递很少,但如果Ref更复杂和沉重,那么它可能最终成为一个问题。
所以,我问人们他们对上述内容的看法......并提出一些建议。显然,您可以构造Ref并通过引用传递,或者更改运算符重载以获取对象而不是引用,但它实际上更多地是关于Visual Studio和gcc之间的这种差异以及您的意见。
答案 0 :(得分:2)
gcc是正确的,你需要const Ref& r
才能编译。
Ref(a, sizeof(a))
创建一个临时的,只能绑定到常量左值引用。
Microsoft编译代码的原因是由于其不合规的邪恶扩展允许非const左值引用绑定到临时代码。与/W4
编译以获得有关它的警告。
答案 1 :(得分:2)
MSVC有一个扩展,允许将对非const的引用绑定到临时对象。这是非标准行为。 Gcc没有这样的延伸和正确的抱怨。
ss >> Ref(a, sizeof(a));
// ^^^^^^^^^^^^^^^^^^
// temporary
friend std::stringstream& operator>>(std::stringstream& ss, Ref& r)
// reference to non-const ^^^^^^
显然,您可以构造Ref并通过引用传递,或者更改运算符重载以获取对象而不是引用。
如果您需要在调用Ref
后使用operator>>
对象,则后者不是真正的选项。前者是要走的路。
答案 2 :(得分:1)
问题是您正在尝试将临时绑定到非const左值引用,这在标准C ++中是不允许的。 Visual Studio有一个扩展程序,可以编译代码,而GCC则符合标准。
您可以完全避免传递临时问题:
Ref r(a, sizeof(a));
ss >> r;