Является ли следующее поведение неопределенным?

#c #undefined-behavior

#c #неопределенное поведение

Вопрос:

Ниже приведена встроенная (определенная внутри файла заголовка) статическая функция-член. Всегда ли гарантируется, что литеральная строка «MyClass» будет находиться в статической памяти? Если нет, не будет ли это возвращать указатель в стеке?

 const char * className()
{
return "MyClass";
}
  

Редактировать:

Как насчет этого?

 const RWCStringamp; className()
{
return "MyClass";
}
  

RWCString это строковый класс, который имеет неявный конструктор, который принимает const char* .
http://www.roguewave.com/portals/0/products/sourcepro/docs/11/html/toolsref/rwcstring.html

Комментарии:

1. Я даже никогда не слышал RWCString … XD Но я предполагаю, что это нормально, поскольку конструктор должен будет позаботиться об этом.

2. @Mysticial но функция будет создавать новую строку RWCString при каждом вызове с использованием неявного конструктора. Каждый вызов className() возвращает новую ссылку

3. Я исправлен. Мой комментарий неверен, поскольку вы не можете вернуться по ссылке подобным образом.

Ответ №1:

Первый пример:

 const char * className()
{
  return "MyClass";
}
  

нормально. "MyClass" это литерал типа char const[8] , время жизни которого начинается до вызова вашего кода и заканчивается после завершения вашего кода, поэтому проблем нет.

Однако второй пример не будет работать.

 const RWCStringamp; className()
{
  return "MyClass";
}
  

Для этого требуется, чтобы объект типа RWCString and был создан внутри функции, чтобы иметь возможность возвращать ссылку на него. Однако то, что создается как локальная переменная или временная внутри функции, не может быть возвращено по ссылке, поэтому вы получаете неопределенное поведение (если оно компилируется).

Вы можете очень просто превратить его в «хорошую» функцию, хотя:

 const RWCStringamp; className()
{
  static RWCString const N = "MyClass";
  return N;
}
  

Здесь я создаю локальный статический объект N , который будет создан при первом вызове функции. Поскольку static его время жизни истекает после вызова, поэтому можно вернуть ссылку на него.

РЕДАКТИРОВАТЬ: как указал Стив, temporary здесь более подходит, чем локальная переменная.

Комментарии:

1. Быстрый вопрос: какова цель возврата по ссылке ( const RWCStringamp; ), если значение не может быть создано внутри функции? (поскольку оно выпадет из области видимости)

2. @Mysticial: в целом? Значение может быть получено из одного из аргументов. Например: std::string constamp; find(std::map<int, std::string> constamp;); , там результатом является одно из значений в карте. Поскольку карта предоставляется вызывающим объектом, вы можете безопасно вернуться по ссылке (к этому вызывающему объекту). Однако легко передать ссылку далеко вверх по цепочке вызовов и оказаться в точке, где это не имеет смысла, поэтому со ссылками и указателями трудно иметь дело.

3. «то, что создается как локальная переменная» — или, в данном случае, то, что создается как временная.

Ответ №2:

Нет. Это полностью определено. Строка не находится в стеке. Это в глобальной памяти. Таким образом, указатель, который он возвращает, является действительным. (еще лучше: вы объявили это const )