宏定义中预处理器标记周围的两个双引号 我不理解在C++中使用字符串的两个双引号的重要性。我在某处看到了以下代码: class str_literal; static str_literal operator"" _s(const char *s, size_t len); class str_literal { private: explicit str_literal(const char *s) : m_str(s) //&(STRING_LITERAL(s))) {} const char *m_str; public: friend str_literal operator"" _s(const char *s, size_t len); }; static str_literal operator"" _s(const char *s, size_t len) { return str_literal(s); } #define S(str) "" str "" _s

宏定义中预处理器标记周围的两个双引号 我不理解在C++中使用字符串的两个双引号的重要性。我在某处看到了以下代码: class str_literal; static str_literal operator"" _s(const char *s, size_t len); class str_literal { private: explicit str_literal(const char *s) : m_str(s) //&(STRING_LITERAL(s))) {} const char *m_str; public: friend str_literal operator"" _s(const char *s, size_t len); }; static str_literal operator"" _s(const char *s, size_t len) { return str_literal(s); } #define S(str) "" str "" _s,c++,c++11,string-literals,user-defined-literals,C++,C++11,String Literals,User Defined Literals,为什么不公开构造器并这样做呢 #define S(str) str_literal(str) 它们是不必要的。编写代码的人可能打算使用这样一个事实,即预处理器将连续的C字符串文本连接成一个文本,例如,S(“hi”)会导致“hi”“”\u S,而这反过来又会导致“hi”\u S 但是,不需要在宏定义中有第一个“。而且也不需要第二个“,因为我们可以使用。: #define S(str) str ## _s 这具有完全相同的效果,并且是惯用的。预处理器将无法区分str内部的str\u s,以便用输

为什么不公开构造器并这样做呢

#define S(str) str_literal(str)

它们是不必要的。编写代码的人可能打算使用这样一个事实,即预处理器将连续的C字符串文本连接成一个文本,例如,
S(“hi”)
会导致
“hi”“”\u S
,而这反过来又会导致
“hi”\u S

但是,不需要在宏定义中有第一个
。而且也不需要第二个
,因为我们可以使用

#define S(str) str ## _s

这具有完全相同的效果,并且是惯用的。

预处理器将无法区分
str
内部的
str\u s
,以便用输入参数替换它。有一组特定的适当分隔符,允许预处理器确定每个给定表达式中的标记(我认为是空格、圆括号,差不多就是这样)。明白了。删除了问题的最后一部分。这仍然是使用两个双引号的唯一目的吗?我第一次看到这种语法。我认为这应该有助于回答你的问题,如果你不只是指预处理器stringif构造函数不是公共的,以便禁用“非文字文字”的创建;您不应该能够编写
str\u literal(some\u function())
。显示字符串连接的替代方法为什么不定义S(str)“str”\u S?空格的重要性是什么?(大多数)空格也是不必要的,但许多人会发现这一点令人困惑,因为
str
实际上是不同的标记,但如果将它们直接相邻而没有空格,则表明它们形成了单个预处理器标记。类似地,在我的代码中,
##
是一个运算符,所以我总是用空格将其包围。此外,在初始的
str
之间需要有一个空格,因为
”str
确实为预处理器形成了一个标记,所以它不会尝试替换
str