std::string和std::wstring的正向声明
forward declaration of std::string and std::wstring
经常讨论无法转发声明std::string和std::wstring的问题。据我所知,原因是这些类型是模板类basic_string:实例化的类型定义
namespace std {
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
}
并且该语言不允许typedef的前向声明。
使用继承而不是typedef:的c++标准不是更好吗
namespace std {
class string : public basic_string<char> {};
class wstring : public basic_string<wchar_t> {};
}
这样我们就可以转发声明std::string和std::wstring了吗?
对于c++标准来说,使用继承而不是typedef〔…〕不会更好
没有。
std::basic_string不意味着以任何形式继承。这个限制允许实现std::basic_string,因为它没有虚拟函数表,所以创建和销毁成本更低(更快(。
如果您需要定义std::[w]字符串,只需#include
it.
编辑(回答评论(
C++(以及标准库(的指导原则之一是"不要为你不使用的东西付费"。这意味着代码是以这样一种方式编写的,即您不应该为不需要的功能产生运行时成本。
如果每个实例都有一个虚拟表,那么创建一个std::string实例的成本会高得多(这将使在性能关键代码中禁止使用std::字符串(。
相反,std::string旨在作为一种快速、类型安全的C char*
机制的RAII实现。类似地,您不应该尝试从std继承:vector、list、map、shared_ptr、unique_ptr等等
如果您真的需要一个字符串基类,可以考虑自己编写一个your_namespace::[w]string_base
(一个微不足道的实现是在内部封装std::[w]string
(。
"typedef派生类"并不等同于真正的typedef。
想象一下,我有一个功能应该同时适用于两个版本:
template <typename Ch>
void foo(const std::basic_string<Ch>& s) {
// do some stuff here
}
我需要做的事情包括调用第三方函数bar
,它作为std::string
和std::wstring
的重载而存在,但不是作为模板:
void bar(const std::string& s) {}
void bar(const std::wstring& s) {}
然后,如果你有一个真正的typedef,那就行了。如果使用继承,它将无法编译,或者将静默地创建要传递给bar
的字符串副本,这是一个隐藏的性能陷阱。
或者采用substr
成员函数。它返回与被调用时相同的类型,但这意味着如果它是basic_string
的成员,则不会返回string
或wstring
(如果它们不是真正的typedef(。这导致了各种微妙的问题。
- 在声明中合并两个常量"std::set"(不是在运行时)
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- std::带有前向声明的变体
- 如何在 C++ 中转发声明 std::set?
- 警告:忽略模板参数上的属性..在 std::unique_ptr (-wignore 属性)的声明中
- 错误:在 C++ 'std'使用未声明的标识符
- 如果在 2 个线程中使用,是否值得将size_t声明为 std::atomic?
- 可以使用<size_t>static_const(),std::as_const()或static_cast<const size_t>()来声明数组吗?
- 向量索引变量声明(size_t 或 std::vector<DATATYPE>::size_type)
- 用于从 ANSI 字符串转换为 std::basic_string <TCHAR>的正确函数声明
- 为什么使用与父级声明的 std::function 在与子级一起使用时会显示错误?
- 怎么可能写 f( *this, std::forward<Args>(args)... ) 而 f 只用 F f 声明;
- c++17通过生成预先声明的类型列表的笛卡尔乘积来生成std::变体
- 如果真的需要std::move,我们应该什么时候声明右值refs
- 使用 std::move 将参数传递给函数,如果该参数声明为按值传递或使用移动操作数 &&,是否有区别?
- 正在声明多维std::数组
- std变体和正向声明
- 在变量名后声明带有 () 的非内部类型与不使用变量名的行为不同。即 std::map<int,char>x(); - 这是怎么回事?
- 为什么在不使用时在此处声明 std::unique_lock
- std::enable_if 更改成员 *变量* 声明/类型