为什么将字符串字面值传递给函数时会分配内存?C++

5
我有他的代码:
int setAttrib(const string& name, int components){    
    // here I don't even touch 'name'
    if(components == 2) return 3;
    else return 1;
}

我这样调用函数:

setAttrib("position", 3);

我正在使用Xcode分析器对内存进行分析,发现在函数调用中std :: string正在进行分配。
为什么会这样?
编辑:
有什么最好的方法可以避免这种分配吗?因为我经常调用那个函数,大约在10秒钟的时间内,我在那一行上分配了约10MB的内存。
谢谢。

这取决于你的编译器。有些编译器不会为这样一个短字符串分配动态内存。[https://dev59.com/4nM_5IYBdhLWcg3wPAfT] - Bo Persson
3个回答

14

你请求一个const string&,但传入了一个const char*。编译器因此需要创建一个正确类型的临时对象。

"position"不是std::string而是char const*这个事实更多的是历史原因(继承自C,在C ++中没有string类),而不是设计决策,但仍需谨记。


1
+1 因为这是唯一一个涉及关键问题的回答:字符串字面值没有类型 std::string - James Kanze
解决“多次”分配的方法是在setAttrib(“position”...)之前一行中创建静态std :: string attrName(“position”),并用attrName变量替换const文字。 - Kamil Klimek
@Kamil:你甚至可以在命名空间中定义它,作为一个常量。 - Matthieu M.

6
由于std::string通常会分配堆内存来保存字符串。在这种情况下,std::string是从字符串字面量(本身位于静态存储区)隐式构造出来的。一些字符串实现使用小缓冲区来服务小字符串,但这似乎不是这里的情况,并且与实现有关。 name没有被使用并不重要 - 基本上,setAttrib("position", 3)setAttrib(std::string("position"), 3);的简写,因此当控制进入setAttrib时,内存已经被分配(当然,在您的孤立代码示例中,编译器可以将getAttrib内联,然后完全放弃字符串构造,但这是编译器优化,而不是语言特性)。
请注意,函数调用期间创建的临时对象在函数返回时会自动销毁,因此不会泄漏内存。

然后完全放弃字符串构造。构造函数永远不会被优化掉。它们可能具有类似RAII的副作用。 - IronMensan

5
为了调用函数,编译器需要构造所有参数,包括const string& name,在您的情况下(您传递一个字符串字面量),唯一的方法是构造一个临时的std::string,这在大多数实现中需要堆内存分配。无论您是否在函数内部使用该值,都不重要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接