【发布时间】:2013-11-06 08:30:38
【问题描述】:
鉴于这个最小的例子。
#include <iostream>
#include <string>
void print_ptr(const std::string& s)
{
const char* data = s.data();
std::cout << "ptr: " << (void*)data << std::endl;
}
std::string str_return(const char* suffix)
{
std::string s("prefix");
s += " ";
s += suffix;
print_ptr(s);
return s;
}
int main()
{
std::string s = str_return("suffix"), t;
print_ptr(s);
t = str_return("suffix2");
print_ptr(t);
return 0;
}
我是这样编译的:
g++ -std=c++98 -fno-elide-constructors -g -Wall str_return.cpp -o str_return
我的 g++:
gcc version 4.7.1
输出:
ptr: 0x804b04c
ptr: 0x804b04c
ptr: 0x804b07c
ptr: 0x804b07c
为什么指针仍然相等?
- 它不应该是返回值优化 - 我把它关掉了
- 它不应该是移动构造函数,因为我采用了一个非常古老的 c++ 标准
如何禁用此行为?
【问题讨论】:
-
有什么理由这样做吗?
-
@JurajBlaho 我只是想确定它不是副本的原因是什么。这样,我就知道快速返回字符串需要什么。
-
仅供参考:当使用 clang (3.2) 和 gcc libstdc++ 编译时,我在从
str_return()返回时遇到分段错误。 这强烈暗示了库的错误/非标准行为。使用 llvm libc++ 时,指针是不同的(尽管它在t中重用了s.data(),即第 1 行和第 3 行报告相同的 ptr)。 -
@Walter,这意味着您的 clang 安装失败了,而不是 libstdc++ 中存在错误。 libstdc++ 对其
std::string使用 Copy-On-Write,它 100% 符合 C++03(本示例使用) -
如果您想阻止 Copy-On-Write 共享缓冲区,则显式复制缓冲区:
std::string copy(s.data(), s.size()),但在此示例中,这只是一种有害的悲观化,因为在str_return之后返回s和t无论如何都不会与另一个对象共享他们的数据。
标签: c++ copy-constructor return-value-optimization