相关疑难解决方法(0)

如何在没有Singleton的情况下实现方便的日志记录?

我目前的实施,简化:

#include <string>
#include <memory>

class Log
{
  public:
    ~Log() {
      // closing file-descriptors, etc...
    }
    static void LogMsg( const std::string& msg )
    {
      static std::unique_ptr<Log> g_singleton;
      if ( !g_singleton.get() )
        g_singleton.reset( new Log );
      g_singleton->logMsg( msg );
    }
  private:
    Log() { }
    void logMsg( const std::string& msg ) {
      // do work
    }
};
Run Code Online (Sandbox Code Playgroud)

总的来说,我对此实现感到满意,因为:

  • 懒惰的实例化意味着我不付钱,除非我使用它
  • 使用unique_ptr意味着自动清理,因此valgrind很高兴
  • 相对简单,易于理解的实施

但是,负面因素是:

  • 单身人士不利于单元测试
  • 在我的脑海中引入一种伪全局(一点代码气味)的不和谐

所以这里是我的问题针对那些成功从他们的C++代码中驱逐所有单例的开发人员:

  • 您在应用程序范围的日志记录中使用什么类型的非Singleton实现?
  • 接口是否像上面的Log :: LogMsg()调用一样简单易用?

我想避免在我的代码中传递一个Log实例,如果可能的话 - 注意:我问,因为,如果有一个好的,合理的选择,我也想从我的代码中驱除所有Singletons.

c++ singleton c++11

39
推荐指数
3
解决办法
2万
查看次数

为什么`operator <<`的`basic_ostream`的rvalue重载返回左值引用?

§27.7.3.9为以下内容定义以下重载operator<<:

template <class charT, class traits, class T>
  basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>&& os, const T& x);
Run Code Online (Sandbox Code Playgroud)

效果: os << x
退货: os

(§27.7.2.6定义rvalue重载operator>>.)
基本上,它只是转发到左值超载.我认为这个重载非常危险(实际上istreamostream实际更重要),请考虑以下内容:

#include <sstream>
#include <iostream>

int main(){
  auto& s = (std::stringstream() << "hi there!\n");
  std::cout << s.rdbuf(); // oops
}
Run Code Online (Sandbox Code Playgroud)

关于Ideone的实例(未定义行为的完美示例.在MSVC10上没有为我打印).

上面的例子看起来做作,但它不应该太难进入这个情况在通用代码或传递时(std::stringstream() << "text"),以提供一个左值和一个右值过载和存储功能std::ostreamstd::istream以不同的方式根据过载.

现在,又将返回a basic_ostream<charT, traits>&&并指定以下内容的参数是什么?

返回: move(os)

(同样的basic_istream.)

有什么我可以忽略的吗?在目前的状态,在我看来,它看起来很危险,就像一个缺陷.我浏览了LWG问题列表并找到了这个提议(嗨@HowardHinnant!).它确实会返回一个右值,但是只为能够链这个特殊的运营商,而不是专门针对我上面描述的安全问题(尽管它肯定是额外的好处,确实 …

c++ iostream rvalue-reference c++11

24
推荐指数
1
解决办法
1284
查看次数

使用C++ ifstream从文本文件中读取整数

我想从文本文件中读取图形邻接信息并将其存储到矢量中.

  • 该文件具有任意行数

  • 每一行都有以'\n'结尾的任意整数数

例如,

First line:
0 1 4
Second line:
1 0 4 3 2
Thrid line:
2 1 3
Fourth line:
3 1 2 4
Fifth line:
4 0 1 3
Run Code Online (Sandbox Code Playgroud)

如果我一次使用getline()读取一行,我该如何解析该行(因为每行有可变数量的整数)?

有什么建议?

c++

19
推荐指数
2
解决办法
5万
查看次数

我可以使用流操作符重写日志宏以使用C++模板函数吗?

我们的项目使用宏来使单行语句中的日志记录变得简单和简单,如下所示:

DEBUG_LOG(TRACE_LOG_LEVEL, "The X value = " << x << ", pointer = " << *x);
Run Code Online (Sandbox Code Playgroud)

宏将第二个参数转换为stringstream参数,并将其发送到常规C++记录器.这在实践中非常有用,因为它使多参数记录语句非常简洁.然而,斯科特·迈尔斯说,在有效的C++第3版,(第2项)"您可以通过使用一个内联函数模板获得的宏所有的效率加上所有常规函数的可预测的行为和类型安全".我知道在C++中与可预测行为相关的宏用法有很多问题,所以我试图在代码库中尽可能多地消除宏.

我的日志宏定义类似于:

#define DEBUG_LOG(aLogLevel, aWhat) {  \
if (isEnabled(aLogLevel)) {            \
  std::stringstream outStr;            \
  outStr<< __FILE__ << "(" << __LINE__ << ") [" << getpid() << "] : " << aWhat;    \
  logger::log(aLogLevel, outStr.str());    \
}
Run Code Online (Sandbox Code Playgroud)

我已多次尝试将其重写为不使用宏的内容,包括:

inline void DEBUG_LOG(LogLevel aLogLevel, const std::stringstream& aWhat) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

和...

template<typename WhatT> inline void DEBUG_LOG(LogLevel aLogLevel, WhatT aWhat) {
    ...  }
Run Code Online (Sandbox Code Playgroud)

无济于事(以上两个重写都不会在第一个例子中编译我们的日志代码).还有其他想法吗?可以这样做吗?或者最好把它留作宏?

c++ macros effective-c++

8
推荐指数
2
解决办法
3537
查看次数

这是一个对临时的引用到非const绑定的实例吗?

免责声明:这个问题是为了解.我将boost::lexical_cast在现场使用.已经有点想出了在现实世界中的地方,虽然.


采取以下 "内联"lex-cast方法的尝试:

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

int main()
{
    const std::string s = static_cast<std::ostringstream&>(
       std::ostringstream() << "hi" << 0
    ).str();
    std::cout << s;
}
Run Code Online (Sandbox Code Playgroud)

结果是这样的0x804947c0,因为operator<<它的作用"hi"是一个自由函数,其LHS必须采用std::ostream&,而临时std::ostringstream()不能绑定到ref-to-non const.唯一剩下的比赛是operator<<这需要const void*在RHS ††.

现在让我们交换操作数:

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

int main()
{
    const std::string s = static_cast<std::ostringstream&>(
       std::ostringstream() << 0 << "hi"
    ).str(); …
Run Code Online (Sandbox Code Playgroud)

c++

5
推荐指数
1
解决办法
181
查看次数

stringstream的第一个字符串参数保存为指针/垃圾

可能重复:
在C++中将字符串打印到临时流对象
std :: ostringstream打印c-string的地址而不是其内容

我正在尝试使用stringstream构建一个字符串,就像你使用cout一样.这适用于类似日志记录的类.我遇到的问题是,如果<<运算符的第一个参数是一个字符串,当我随后使用stringstream :: str()调用打印出该字符串流时,我得到一个垃圾地址,而不是字符串.这只发生在FIRST字符串中.后续字符串很好.数字总是好的.这是代码:

    // class I use to print out the stream
    class StreamWriter
    {
    public:
        StreamWriter()
        {}

        ~StreamWriter()
        {
            std::string myMessage = m_stringstream.str();
            std::cout << myMessage << std::endl;
        }

        std::stringstream m_stringstream;
    };

    // macro for simplification
    #define OSRDEBUG (StreamWriter().m_stringstream)

    // actual use
    OSRDEBUG << "Hello " << "my " << "name is Pris " << 123456;

    // output
    0x8054480my name is Pris 123456
    0x8054480my name is Pris 123456
    0x8054480my name is Pris 123456
    0x8054480my …
Run Code Online (Sandbox Code Playgroud)

c++ pointers stringstream memory-address

4
推荐指数
1
解决办法
1089
查看次数

是否可以将内存地址保存为字符串?

说我有一个对象

MyObj stuff;
Run Code Online (Sandbox Code Playgroud)

为了得到东西的地址,我会打印

cout << &stuff << endl; 0x22ff68
Run Code Online (Sandbox Code Playgroud)

我想在字符串中保存0x22ff68.我知道你不能这样做:

string cheeseburger = (string) &stuff;
Run Code Online (Sandbox Code Playgroud)

有没有办法实现这个目标?

c++

4
推荐指数
3
解决办法
5327
查看次数

为什么实例化流操作符模板而不是全局重载操作符?

假设以下代码.有一个类MyStream女巫有模板重载operator <<.全局重载运算符MyStream&operator <<(MyStream&,const MyClass&).令人困惑的事情是(通过编译器)为两个几乎相同的情况生成不同的方法(参见main()函数的主体).我认为应该在两种情况下使用全局运算符,但事实并非如此.为什么这样?

#include <iostream>

class MyStream;
class MyClass;
MyStream& operator << (MyStream& stream, const MyClass&);

class MyStream
{
public:
    template <typename T>
    MyStream& operator << (const T&)
    {
        std::cout << __FUNCTION__ << " " << typeid(T).name() << std::endl;
        return *this;
    }
};

class MyClass
{
};

MyStream& operator << (MyStream& stream, const MyClass&)
{
    std::cout << __FUNCTION__ << " " << typeid(MyClass).name() << std::endl;
    return stream;
}

int main(int, char**)
{
    // 1. Used globally defined operator for …
Run Code Online (Sandbox Code Playgroud)

c++ operator-overloading

3
推荐指数
1
解决办法
158
查看次数

为什么输出一个字符串到未命名的std :: ofstream而不是给我一个十六进制数?

我试图将一些调试输出添加到C++ 03项目中并得到一些奇怪的结果.这是简化的测试代码:

#include <fstream>

int main()
{
    {
        std::ofstream file("/tmp/test.txt");
        file << "hello" << " ... OK, this works\n";
    }
    std::ofstream("/tmp/test.txt",std::ios_base::app) << "hello"
                                                      << " ... no, I mean hello!\n";
}
Run Code Online (Sandbox Code Playgroud)

出于某种原因,这是我在编译后得到的:

$ g++ test.cpp -o test && ./test && cat /tmp/test.txt
hello ... OK, this works
0x80487fe ... no, I mean hello!
Run Code Online (Sandbox Code Playgroud)

为什么在将字符串输出到未命名std::ofstream对象的情况下会得到十六进制数?为什么第二个字符串的后续输出有效?

c++ string fstream ofstream

3
推荐指数
1
解决办法
128
查看次数