2017-02-02 5 views
1

Предположим, у меня есть функция, которую мне нужно вызвать пару раз, которая принимает строковый литерал как его первый и единственный параметр. Вроде так:Строка строки инициализации указателя

func("things_i_like\\turtles\\fresh_water"); 

/* some code */ 

if (turtleFred.mood == happy) 
{ 
    func("things_i_like\\turtles\\fresh_water"); 
} 

/* more code */ 

func("things_i_like\\turtles\\fresh_water"); 

Теперь, если мне когда-либо понадобится изменить этот строковый литерал, мне придется изменить его в 3 разных местах. Если бы я делал опечатку в одном из строковых литералов при их изменении, могло произойти что-то плохое. Чтобы избежать этого, я мог бы использовать переменную для хранения местоположения строкового литерала. Например:

const char* turtlesPath = "things_i_like\\turtles\\fresh_water"; 

func(turtlesPath); 

/* some code */ 

if (turtleFred.mood == happy) 
{ 
    func(turtlesPath); 
} 

/* more code */ 

func(turtlesPath); 

У меня есть 3 проблемы с этим подходом. Предположим вместо одного строкового литерала у меня около 20-30.

Проблема № 1: Если все указатели, которые держат расположение строковых литералов инициализируются, как они определены, таким образом, в начале сферы. И программа вводит условие, которое никогда не будет использовать эти строковые литералы, означает ли это, что код, который был выполнен для назначения строковых литералов указателям (инициализация), был ненужным и расточительным?

Проблема № 2: Если указатели, которые держат расположение строковых литералов и инициализируется в функции обратного вызова, которая может вызываться рекурсивно, не будет, которые оказывают значительное влияние на пространство для хранения из стек?

Что я конкретно имею в виду: это может быть не проблема вообще, только при использовании нескольких указателей, которые содержат места для строковых литералов, но это может стать проблемой при использовании многих из них. Таким образом, при добавлении большего количества указателей это может привести к переполнению стека.

И не означает ли это, что указатели должны будут инициализироваться каждый раз, когда вызывается функция? Что, если их много, а функция называется тысячами раз в день, не будет ли это накладывать большие накладные расходы?

Проблема № 3: Возможным решением было бы использовать макросы для строковых литералов, например, так:

#define TURTLES_PATH "things_i_like\\turtles\\fresh_water" 

Но это кажется не очень очень-великая вещь, чтобы сделать.

Похоже, что я что-то упускаю. Некоторые предложения или общий подход к тому, как с этим бороться, будут высоко оценены. Рефакторинг можно использовать, чтобы избежать проблемы до некоторой степени, но она не обеспечивает решение реальной проблемы.

ответ

1

Вы правы заподозрить, что переменный вид

const char *turtlesPath = "things_i_like/turtles/fresh_water"; 

скрыл над головой относительно ввода строковых литералов рядного, который станет значительным, если вам нужны их тысячи. Вы не правы о , что это накладные расходы. Это не операции инициализации во время выполнения и не стековое пространство. Это называется так называемый динамических переездах, которые я не могу объяснить кратко, я могу указать только на целую книгу: Linkers and Loaders от John Levine.

Лучшее исправление, на самом деле, использовать #define макросы в файле заголовка,

#define turtlesPath "things_i_like/turtles/fresh_water" 

Ни один из недостатков C макросов препроцессора не применяются к данному конкретному использованию, и ни одна из альтернатив не дают компилятор столько свободы для оптимизации.


P.S. Не помещайте пробелы внутри своих круглых скобок. Когда вы помещаете пробелы внутри своих круглых скобок, это заставляет ребенка кричать.

Смежные вопросы