Невозможно отключить оптимизацию возвращаемого значения для std :: string?

Учитывая этот минимальный пример.

#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

Мой г ++:

gcc version 4.7.1

Выход:

ptr: 0x804b04c
ptr: 0x804b04c
ptr: 0x804b07c
ptr: 0x804b07c

Почему указатели все еще равны?

  • Не должно быть оптимизации возвращаемого значения — я выключил
  • Это не должно быть перемещение конструкторов, так как я взял действительно старый стандарт C ++

Как я могу отключить это поведение?

3

Решение

Оптимизация возвращаемого значения влияет на локальный объект (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);
}
6

Другие решения

Возможно, вы не испытываете RVO. Наблюдаемое поведение может быть вызвано копией при оптимизации записи, используемой в реализации std::string в GCC. Следовательно, конструктор копирования может фактически выполняться, но выделенный буфер не копируется.

1

Я не могу комментировать ответы, поэтому я поставлю свое уведомление здесь:
Если вы поставите конструктор, вызовите для вас строку s, и после этого вы вызовете 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
0
По вопросам рекламы [email protected]