2016-10-19 41 views
1

我在C++中有一个类,我希望能够打印一个对象,所以我创建了一个char *转换运算符。事情是,由于某种原因,运算符函数的输出是随机符号而不是我返回的字符串。 下面的代码:用char *运算符随机输出

operator const char*()const { 
    std::cout << (std::to_string(Nom) + '/' + std::to_string(Denom)).c_str() << std::endl; 
    return (std::to_string(Nom) + '/' + std::to_string(Denom)).c_str(); 
} 

和主要功能:

Rational r1(7, 15); 
std::cout << r1<<std::endl; 
return 0; 

第一行输出normaly( “7/15”),但返回值就是随机的字母。

任何线索?

+1

你认为c_str()有什么作用? – UKMonkey

+3

您可以在临时对象上调用'c_str()'。在您的操作员返回之前,结果是一个悬挂指针,甚至在之前。 – StoryTeller

+0

'std :: string'具有'c_str()'而不是'operator char *()'的原因是为了让它更明显,像这样的代码正在做一些严重错误的事情。 –

回答

0

对他人的补充答案:通常隐式的转换运算符是一种不好的风格。特别是一个与你的班级无关的类型。

如果你想投你的目标,更好的方法可能是一个明确的转换:

class Rational 
{ 
public: 
    ... 
    std::string toString() const 
    { 
     return std::to_string(Nom) + '/' + std::to_string(Denom); 
    } 
}; 

可以重载的“走出去”的功能吧:

std::ostream & operator <<(std::ostream &stream, const Rational &obj) 
{ 
    stream << obj.toString(); 
    return stream; 
} 

如果你只需要你也可以使用超负荷而不用强制转换功能:

class Rational 
{ 
public: 
    ... 
    friend std::ostream & operator <<(std::ostream &stream, const Rational &obj) 
    { 
     stream << std::to_string(obj.Nom) + '/' + std::to_string(obj.Denom); 
     return stream; 
    } 
}; 
4

(std::to_string(Nom) + '/' + std::to_string(Denom))创建一个临时变量。 .c_str()获取该变量拥有的一些内存的地址。

不久后,该变量被销毁(您不会复制/移动到任何地方)。内存被释放。

你从c_str()获得的地址是保留的,但现在它指向一些内存,它可能或可能不是你的应用程序的一部分。试图阅读这是未定义的行为(或简称UB在这个网站)。

3

替代返回管理内存的对象,而不是原始的const char*

operator std::string() const { 
    std::stringstream ss; 
    ss << Nom << '/' << Denom; 
    return ss.str(); 
} 
+3

如果您需要const char *运算符(而不是std :: string),则将该字符串的副本保留为类的成员,然后可以返回该类的.c_Str()。 – UKMonkey

+0

我会进一步建议让字符串变成'mutable'成员,并添加一个可变的“state changed”bool,这样就可以使用懒惰的评估和缓存而不会破坏类的const正确性。这允许您将字符串创建逻辑放入运算符中,以便实际代表字符串仅在第一次调用运算符时生成,并且只有在实例的状态自上次调用后发生更改时才会更新。 –