我在这里剪掉了我班上不相关的部分。我不知道我做错了什么,只是想尝试cout<<对象。
#include <iostream>
class Snipped
{
public:
friend std::ostream& operator<<(std::ostream& os, const Snipped& s);
protected:
private:
};
std::ostream& operator<<(std::ostream& os, const Snipped& s)
{
os << "test";
return os;
}
int main(int argc, char* argv[])
{
Snipped* s = new Snipped();
std::cout << s << std::endl << s;
delete s;
return 0;
}
预期产出:
test
test
实际输出:
0x12ae20
0x12ae20 (random memory location?)
答案 0 :(得分:8)
std::cout << s << std::endl << s;
您正在使用地址呼叫<<
,您需要使用Snipped
类型的对象来呼叫它。
上面的代码行不会调用重载的运算符函数,因为重载函数的参数不匹配。
您需要致电:
std::cout << *s << std::endl << *s;
这可确保调用<<
重载的操作符函数,因为参数与之匹配。
答案 1 :(得分:6)
尝试
std::cout << *s << std::endl;
顺便说一下,
std::cout << s << std::endl;
实际上不是随机内存位置。
在这种情况下,它是堆上的实际内存地址。
您实际上可以使用该地址来检查对象的身份。
这在调试或实际代码中很有用。 例如,如果你看一下赋值运算符,你会经常看到:
class Foo
{
Foo& operator=( const Foo& foo )
{
// use the identity principle
if ( &foo==this )
return *this; // so I don't waste CPU cycles copying to myself
// ...really do copy here
return *this;
}
};
答案 2 :(得分:2)
虽然只是取消引用指针(即使用'* s'而不是's'),有一条更大的鱼可以炒!除非有充分的理由将对象放在堆上,否则不应该这样做:
int main()
{
Snipped s;
std::cout << s << '\n' << s;
}
我发现在我编写的程序中使用new
等等delete
非常罕见。除了更简单的代码之外,这也很方便地产生更快的程序。如果你真的需要在堆上分配一些东西,可以使用某种智能指针来确保对象自动释放:
int main()
{
std::unique_ptr<Snipped> s(new Snipped);
std::cout << *s << '\n' << *s;
}
作为旁注,请不要使用std::endl
,除非您真的打算刷新流:我发现不恰当地使用std::endl
不止一次成为大规模性能问题的根本原因。当然,大部分时间都没关系,但在更多情况下,你不关心同花顺。如果您不喜欢使用'\n'
或"\n"
,则可以使用自定义操纵器:
std::ostream& nl(std::ostream& out) { return out << '\n'; }
使用此功能,您可以使用nl
代替std::endl
,并且不会总是冲洗流。