Вы можете использовать такой код:
char *MyFunction(some arguments...)
{
char *pointer = malloc(size for the new array);
if (!pointer)
An error occurred, abort or do something about the error.
return pointer; // Return address of memory to the caller.
}
Когда вы это сделаете, память должна быть освобождена позже, передав адрес бесплатно.
Есть другие варианты , Подпрограмма может возвращать указатель на массив (или часть массива), который является частью некоторой существующей структуры. Вызывающий может передать массив, и программа просто записывает в массив, а не выделяет пространство для нового массива.
Чтобы предотвратить вызовы оператора << ()
от выполнения форматирования вы должны знать тип потока во время компиляции. Это можно сделать либо с помощью макросов, либо с помощью шаблонов.
Мое шаблонное решение следует.
class NullStream {
public:
void setFile() { /* no-op */ }
template<typename TPrintable>
NullStream& operator<<(TPrintable const&)
{ return *this; } /* no-op */
}
template<class TErrorStream> // add TInfoStream etc
class Logger {
public:
TErrorStream& errorStream() {
return m_errorStream;
}
private:
TErrorStream m_errorStream;
};
//usage
int main() {
Logger<std::ofstream> normal_logger; // does real output
normal_logger.errorStream().open("out.txt");
normal_logger.errorStream() << "My age is " << 19;
Logger<NullStream> null_logger; // does zero output with zero overhead
null_logger.errorStream().open("out.txt"); // no-op
null_logger.errorStream() << "My age is " << 19; // no-op
}
Поскольку вы должны делать это во время компиляции, оно, конечно, довольно негибко.
Например, вы не можете решить Уровень ведения журнала во время выполнения из файла конфигурации.
Быстрый Google придумала этот пример, который может быть полезен. Я не даю никаких гарантий, за исключением того, что он компилируется и запускается: -)
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
int main() {
onullstream os;
os << 666;
}
Почему бы не использовать существующие решения для ведения журналов? миллионами пользователей? log4j, log4net, log4cxx .., и это лишь некоторые из них.
Возможно, вам понадобится больше, чем просто форматирование текста и фильтрация сообщений. Как насчет многопоточности?
Я бы реализовал фильтрацию и синхронизацию многопоточности как ответственность отдельного класса.
Тем не менее, ведение журнала является не такой простой задачей, и я бы попытался использовать существующие решения для ведения журнала вместо разработка нового.
все, спасибо за то, что поделились кодом, я просто провожу тест, тогда метод Нила все равно будет формировать строку, например:
#include <streambuf>
#include <ostream>
#include <iostream>
using namespace std;
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
class MyClass
{
int a;
friend ostream& operator<< (ostream&, MyClass const&);
};
ostream& operator<<(ostream& out,MyClass const& b)
{
std::cout<<"call format function!!";
out << b.a;
return out;
}
int main() {
onullstream os;
MyClass obj;
os<<obj;
}
Запустив эту программу, вы обнаружите, что "ostream & operator << (ostream & out, MyClass const & b) ". Таким образом, выполнение форматирования для объекта по-прежнему будет вызываться. Таким образом, мы по-прежнему не можем избежать накладных расходов на форматирование сообщений.