繁体   English   中英

如何在 c++ 中使用宏?

[英]How to use Macros in c++?

最近我在 c++17 中遇到了 inline 以及它如何被用作#define的替代品,但两者都有其缺点。 但是我的问题是,如果我想抽筋整个std::cout << x << '\n'; 在一个名为LOG(x)的简单行中。

答:我应该使用什么,为什么?
B:各有什么优缺点,什么时候用什么?

1.)

#define LOG(x) std::cout << x << '\n'

2.)

void inline LOG(auto x)
{
    std::cout << x << '\n';
}

3.)

void LOG(auto x)
{
    std::cout << x << '\n';
}

4.)

这个是有人推荐给我的:

template <typename T>
void log(const T& x)
{
    std::cout << x << '\n';
}

如何在 c++ 中使用宏?

谨慎。 当没有更好的选择时。


  1. 避免这种情况。 宏名称不遵守范围规则,因此更容易受到名称冲突的影响。 另外,考虑一下如果你想记录一个被另一个数字移位的数字会发生什么:

     LOG(0x1 << 2);

    你会期待什么 output,你会得到什么 output? 他们匹配吗?

  2. 亲:它是一个 function(模板),因此不存在与宏相关的问题。 缺点:您按值接受参数。 例如,经常用于日志记录的字符串可能会很昂贵。 需要 C++20。

  3. 实际上与 2 相同。 auto参数将这些转换为隐式内联的 function 模板。

  4. 优点:不需要 C++20。 传递了一个引用,这对于传递字符串很有好处。

结论:4.是一个合理的默认选择。

普遍的共识是使用宏不是一个好主意。 但这真正意味着滥用宏不是一个好主意。

解决方案#2 可以,但它的用处相当有限,因为每行只能打印一个值。

inline void LOG(const auto& x)
{
    std::cout << x << '\n';
}

// use as:
LOG(x);

这是一个不错的解决方案,但它的使用相当有限。考虑这个用例:

inline void LOG(const auto& x)
{
    std::cout << x << '\n';
}

struct point { float x, y; };

// usability is kind of limited, since it will only print one value per line 
point p{};
LOG(x);
LOG(y);

// which gives this output.
0
0

// That's not really useful for a log.

宏的一个优点是,您可以使日志 output 更有用一些。

#define LOG(x) std::cout << x << '\n'

struct point { float x, y; };

// usability is better, but still limited, 
point p{};
LOG("x: " << p.x << ", y: " << p.y);

// which gives this output.
x: 0, y: 0

这有点好,您正在使用宏,并且您确实可以更好地控制 output,从而使您的日志更有用。 但它对您的代码施加了一些限制......例如,您可能希望在以后使用第三方日志库,或者编写自己的日志库,但是对 LOG() 的某些调用将在其中包含运算符,并且这可能会迫使您重写它们。

因此,除其他外,function 模板会更好,它可以接受任意数量的 arguments。

template <typename... Args>
inline void LOG(Args&&... args)
{
    (std::cout << ... << args) << '\n';
}

point p{};

LOG("x: ", p.x, ", y: ", p.y);

// which gives this output.
x: 0, y: 0

如果你想在你的发布版本中失败,我建议使用宏。

#define LOG(...)

// on MSVC
#define LOG(...) __noop

除非您想在 output 中记录变量的符号名称,否则我不会使用 #1(宏版本),例如:

#define LOG(x) std::cout << #x << " = " << x << '\n' 

我相信 #2 和 #4 是等价的,因为使用 auto 在引擎盖下引入了模板类型。

#3 略逊一筹,因为它要求您在 header 文件中编写声明,并将定义放在源文件中(因为它不是内联的),这需要更多代码来维护。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM