3

给定这个最小的例子。

#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++ 标准

如何禁用此行为?

4

3 回答 3

6

返回值优化会影响本地对象(s在您的str_return函数中)。你从不仪器。

字符串对象本身管理动态内存,并选择在返回时将该托管内存交给下一个字符串。您正在检测的是托管内存。足够明智,这不会改变。

如果您真的想查看 RVO 的效果,请检测本地对象:

#include <iostream>
#include <string>

void print_ptr(const std::string& s)
{
    std::cout << "ptr: " << static_cast<const void *>(&s) << 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");
    print_ptr(s);
    std::string t = str_return("suffix2");
    print_ptr(t);
}
于 2013-11-06T08:33:47.113 回答
1

您可能没有体验 RVO。观察到的行为可能是由std::stringGCC 实现中使用的写时复制优化引起的。因此,复制构造函数实际上可能会运行,但分配的缓冲区不会被复制。

于 2013-11-06T08:34:51.643 回答
0

我不能评论答案,所以我会在这里通知:如果你为你的字符串调用构造函数,然后你调用 str_return - 地址会有所不同:

std::string s; // implicit constructor call
print_ptr( s );
s  = str_return( "suffix" );
print_ptr( s );
std::cout << std::endl;

输出将是:

ptr: 0x28fec4  // for the original s;
ptr: 0x28fec8  // for local variable in function str_return
ptr: 0x28fec4  // the address of s after call str_return didn't change
于 2013-11-06T09:11:54.040 回答