C++ 内联匿名实例和命名实例之间的区别

标签 c++

在日志上下文中,我想使用实用程序类的临时实例来收集一些输出,并使用析构函数来处理收集到的输出。例如,打印到标准输出如下。

我注意到与命名自动实例相比,实用程序实例是否构造为内联匿名实例的行为差异。

命名实例会产生预期的行为和输出。内联实例在第一次插入操作时遇到困难,显然只能处理简单转换为 int 的操作数。

以这些不同方式使用的实例有什么区别?

#include <string>
#include <sstream>
#include <iostream>

class Util
{
public:
    std::ostringstream m_os;

    Util() {}
    ~Util() { std::cout << m_os.str() << std::endl;}
};



int main (void)
{
// ----------- Using temporary anonymous instance - 
    //  Output does not match expected, and the first insertion seems to
    //  only be able to handle instances that can be converted to int.

    // Following prints "97key=val", but expect "akey=val"
    (Util()).m_os << char('a') << std::string("key") << "=" << std::string("val");

    // Following prints "0x80491eakey=val", but expect "Plain old C string key=val"
    (Util()).m_os << "Plain old C string " << std::string("key") << "=" << std::string("val");

    // Following results in syntax error
    // error: no match for ‘operator<<’ in ‘Util().Util::m_os <<
    (Util()).m_os << std::string("key") << "=" << std::string("val");


// ----------- Using named instance - output matches expected

    // Block results in print "akey=val"
    {
        Util inst;
        inst.m_os  << char('a') << std::string("key") << "=" << std::string("val");
    }

    // Block results in print "Plain old C string key=val"
    {
        Util inst;
        inst.m_os  << "Plain old C string " << std::string("key") << "=" << std::string("val");
    }

    // Block results in print "key=val"
    {
        Util inst;
        inst.m_os  << std::string("key") << "=" << std::string("val");
    }

    return 0;
}

最佳答案

(Util())创建一个临时对象。结果,(Util()).m_os也是一个临时对象。

operator<<有一些定义作为成员函数,以及将其作为独立函数的一些其他定义。前者在临时对象上工作,后者不工作,因为临时对象不能绑定(bind)到流引用。将您的代码简化为完整示例:

#include <stdio.h>

struct stream
{
    stream& operator<<(int)
    { puts("operator<<(int)"); return *this; }
};

stream& operator<<(stream& s, char)
{ puts("operator<<(char)"); return s; }

struct streamwrapper
{
    stream s;
};

int main()
{
    streamwrapper w;
    w.s << 'a'; // outputs operator<<(char)

    streamwrapper().s << 'a'; // outputs operator<<(int)
}

由于您预期的重载不可用,而其他重载不可用,因此会使用其他重载而不是给您一个硬编译器错误。

关于C++ 内联匿名实例和命名实例之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19035306/

相关文章:

c++ - 在 C++ 中重载不同类型的比较运算符

c++ - 有没有可能声明一个不占用内存的成员变量?

c++ - 如何摆脱 Eclipse C++ 编辑器中的多余字符

c++ - C++中的依赖注入(inject)

c++ - 禁用关于 "underscore-prefixed user-defined literals"的 GCC 警告

c++ - 编译时PCAP程序错误

c++ - JPG压缩后的原始BGR图像长度相同吗?

c++ - 我可以在运行时检查内置类型吗?

c++ - SIGSEGV 在 C++ 循环中有一个非常大的数组

C++ new int[0]——它会分配内存吗?