2017-01-20 7 views
1

В строке D есть псевдоним по неизменяемому char[]. Поэтому каждая операция по обработке строк с распределением памяти. Я привязался, чтобы проверить это, но после замены символа в строке я вижу тот же адрес.Память распределения для строки

string str = "big"; 
writeln(&str); 
str.replace("i","a"); 
writeln(&str); 

Выход:

> app.exe 
19FE10 
19FE10 

Я попытался использовать ptr:

string str = "big"; 
writeln(str.ptr); 
str.replace(`i`,`a`); 
writeln(str.ptr); 

И получил следующий вывод:

42E080 
42E080 

Так он показывает один и тот же адрес. Зачем?

ответ

2

Вы сделали простую ошибку в коде:

str.replace ("я", "а");

str.replaceвозвращается новая строка с заменой сделал, он фактически не заменить существующую переменную. Попробуйте str = str.replace("i", "a");, чтобы увидеть изменения.

Но вы также сделали слишком широко общее заявление о распределении:

Таким образом, каждый операции по обработке строки с выделением памяти.

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

import std.string; 
import std.stdio; 

void main() { 
     string a = " foo "; 
     string b = a.strip(); 
     assert(b == "foo"); // whitespace stripped off... 

     writeln(a.ptr); 
     writeln(b.ptr); // but notice how close those ptrs are 
     assert(b.ptr == a.ptr + 2); // yes, b is a slice of a 
} 

replace также возвращает исходную строку, если нет никакой замены не было на самом деле сделано:

string a = " foo "; 
string b = a.replace("p", "a"); // there is no p to replace 
assert(a.ptr is b.ptr); // so same string returned 

индексирование и итерации не требуют никаких новых (конечно). Верьте или нет, но даже добавление иногда не выделяется, потому что в конце среза может остаться память (хотя это обычно будет).

Существуют также различные функции, которые возвращают объекты диапазона, которые выполняют изменения по мере прохождения через них, избегая выделения. Например, вместо replace(a, "f", ""); вы можете сделать что-то вроде filter!(ch => ch != 'f')(a); и пропустить цикл, который не выделяет новую строку, если вы ее не попросите.

Так что это намного больше нюансов, чем вы думаете!

+0

какая разница между 'string * str_ptr; str_ptr = &str; writeln (str_ptr); 'и' writeln (str.ptr); ' –

+0

' & str' является указателем на ARRAY, 'str.ptr' является указателем на СОДЕРЖАНИЕ. –

0

В D все массивы - это длина + указатель на начало значений массива. Они обычно хранятся в стеке, и это происходит просто как ОЗУ.

Когда вы отправляете адрес переменной (которая находится в теле функции), то, что вы действительно делаете, это получить указатель на стек.

Чтобы получить адрес значений массива, используйте .ptr. Итак, замените &str на str.ptr, и вы получите правильный результат.

+0

Я проверил его, и он показывает тот же адрес. Мое последнее редактирование темы. –