2012-03-24 66 views
1

我有一个简单的问题。我有一个很长的std :: string,我想把它传递给一个函数。 我想知道这个字符串将被复制到堆栈然后将传递一个副本或类似指针的东西将被传递并且不需要额外的空间?编译器是否将std :: string传递给堆栈,并将其传递给C++中的函数?

(C++)

  • 我还有一个小问题:有多少内存的字符串的元素采取就像char
+0

你在谈论一个'std :: string'吗? – 2012-03-24 12:07:54

+0

你是什么意思的字符串?引用文字?的std :: string? – selalerer 2012-03-24 12:08:36

+0

我的意思是std :: string。 – 2012-03-24 12:10:24

回答

4

是的,它会被深拷贝,所以建议使用const引用。

void fun(const std::string & arg) 

通常的std :: string具有2个字段,一个指针指向动态分配的内存和长度,所以它是在64位计算机16 +实际长度。

+3

我期望至少** 3个字段**:指针,当前长度和最大长度。 – Sjoerd 2012-03-24 12:43:04

+1

没有典型的字符串。 MSVC很胖(但不会为小字符串分配动态内存),而gcc只是一个指向计数缓冲区的指针(因此即使是一个'char'也会分配动态内存)。 – 2012-03-24 19:40:47

0

扰流警报:我的回答不会是相关的,只是一种优化技术。

如果您不想复制字符串,请编写您的自定义字符串类,它具有两个指针或一个大小的指针。在过去,它减少了我很多重复。这将只能以只读方式工作,并执行copy_on_write,即只有遇到写入时才会复制。

+0

对于'std :: string',COW也是可行的,但在实践中通常比复制+小字符串优化要慢。 – Philipp 2012-03-24 14:06:32

0

当在C++中通过值传递参数时,它在概念上被复制。不管这个副本是否真的发生,都是另一个问题,并且取决于参数是如何传递的,并且在某种程度上取决于编译器:显式允许编译器删除某些副本,特别是临时对象的副本。例如,当你从一个函数返回一个对象,并且我们清楚该对象将被返回时,该副本很可能会被忽略。同样,将函数的结果直接传递给另一个函数时,很可能不会被复制。

除此之外,C++ 2011通过支持移动构造函数增加了另一个可能性。这些涵盖了一些扩展类似的基础,但也允许您有更好的控制:您可以明确指出,移动对象而不是被复制是可以接受的。尽管如此,在任何情况下都不会通过引用传递对象。

对于每个元素所使用的字节,std::string只使用sizeof(cT)字节(其中cTstd::basic_string的字符模板参数)。但是,在许多情况下,字符串会重新分配空间,并且当字符添加到字符串时肯定会重新分配空间。您可以通过比较size()capacity()并通过reserve()进行一定程度的控制来确定过度配置,尽管此功能不需要摆脱任何过度配置,但capacity()必须至少与最后一个reserve() d一样多。如果字符串很小(例如最多15个字符),现代实现将不会进行任何分配。这被称为字符串优化

关于字符串的实际表示形式:除非它很小,否则将使用一个字作为存储地址,每个字用于大小和容量,以及具有有状态分配器的字符串的大小分配器(通常是另一个词)。考虑到对齐要求,这意味着在大多数情况下,除了元素之外,字符串还需要四个单词。通常情况下,小字符串优化使用这些字来存储字符,如果字符串放在那里,当然,除非需要存储有状态的分配器。