类中包含的 STL 字符串成员包含在 std::vector 中
STL string member in class contained in std::vector
我有一个c++类Foo,其中有一个stl std::string
作为成员。此外,我有一个 STL std::vector<Foo> vecFoo
,它按值包含类 Foo 的对象(而不是指向 Foo
对象的指针)。现在,一位朋友建议我不要以这种方式实现它,而是使用指针构建向量:std::vector<Foo*>
或使用boost智能指针。他讨论了一个向量,它涉及对其成员的大量复制操作(在添加成员等时分配更多空间)当包含的类具有像std::string
这样的动态成员时会产生问题。可能会出现任何问题吗?
据我了解,当类 Foo 可能被std::vector
复制时,std::string
实际上会执行深度复制(或写入时复制),因为 Foo 为其所有成员调用复制构造函数。我的朋友认为,当向量分配新空间时,如果向量中所有 Foo 对象之间的字符串成员长度不同,这是一个问题。你觉得怎么样?
使用指针在矢量内部Foo
的唯一原因是速度。指向Foo(Foo*
)的指针复制速度比完整的类Foo
快得多,不是吗?谢谢讨论!
,如果您要使用 new
分配每个元素对象,那么使用指针std::vector
根本不会更有效。但是,如果你的元素对象足够大(不是因为字符串长度,而是因为它的"非指针"成员),带有指针的向量可以表现得更好或不 - 这取决于向量重新分配频率。
考虑一下std::vector
很少分配空间对数的事实,因为它分配的空间总是比以前分配的时间多两倍。
C++11 的情况甚至更好,std::vector
将使用移动语义来避免复制字符串字符。但是,如果您的编译器未生成默认的移动构造函数,则可能需要在类中插入移动构造函数才能使此操作正常工作。
甚至在 C++11 之前,一些std::string
实现就使用写入时复制策略,因此仅制作字符串的"深度复制"不需要复制底层字符数组,除非其中一个副本被修改。
如果字符串成员的长度不同,则存在问题 向量中的所有 Foo 对象
这肯定不是问题 - 当然std::string
对象在内部包含指向字符数组的指针,而不是数组本身。
我敢肯定,在做出此类级别的优化决策之前,您应该使用分析器分析您的程序。
这里有一个权衡。你的Foo是否足够复杂,以至于复制它比复制指针或智能指针要贵得多?您是否希望矢量在执行期间频繁调整大小,从而导致复制?或者,复制Foo向量的成本是否可以接受,而不是使用指针(之后必须清理)或智能指针的额外复杂性?在矢量中存储指针有其自身的成本,因为指向的对象不一定在内存中是连续的。(但是,当按值存储时,Foos 中包含的字符串将数据分散在内存中。
尝试简单的实现(Foo的向量),测量其性能,然后才考虑切换到(智能)指针的优化。
您有两种选择:
- 使用 std::
- unique_ptr 或 std::shared_ptr
- 按值使用它并提供移动语义
如果你使用第二个选择 你必须以这种方式定义Foo。
struct Foo
{
// default ctor
Foo( const std::string& s = "" ) : name( s ) {}
// copy ctor
Foo( const Foo& rhs ) : name( rhs.name ) {}
// move ctor
Foo( Foo&& rhs ) : name( std::move( rhs.name ) ) {}
// assign operator
Foo& operator = ( const Foo& f )
{
name = f.name;
return *this;
}
// move operator
Foo& operator = ( Foo&& f )
{
std::swap( name, f.name );
return *this;
}
string name;
};
FooVec v;
// construct in place
v.emplace_back( "foo1" );
v.emplace_back( "foo2" );
// or move
v.push_back( std::move( Foo( "foo3" ) );
- 为什么std::copyable包含std::moveable
- 包含 std::list 的结构体的 C++ 初始化
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- 包含 std::threads 的元素向量
- std::包含 std::函数回调的多个包装器的向量不起作用
- 检查 std::any 变量是否包含 std::string 时出现问题
- 安装 GCC 7.1 是否会在标准库中包含 std::is_base_of_v
- C++ 中的 NAPI 本机模块正在部分执行(包含 std::thread)
- 包含 std::string 常量的类
- 即使在包含 std 命名空间之后,fstream 在 Visual Studio 2017 中也无法正常工作
- 如何重用包含 std::ifstream 的类
- 提升序列化:SIGABRT 同时反序列化包含 std::shared_ptr 的对象上的 boost::shared_p
- 传统C 代码不包含std ::前缀
- 如何在(C )构造函数参数列表中包含std:列表
- 从C++文件中读取包含 std::vector 的对象
- 在头文件中包含std::vector会导致模板实例化错误
- 是否有一个包含std::unique_ptr的c++标准库实现可以与visualstudio2008一起使用
- 包含 std::forward 会产生错误,但其省略会编译.为什么
- 包含std ::队列的类的价值限制
- 为什么结构make_unique在包含 std::p romise 作为成员时失败?