Каков результат следующего утверждения?

std::string p;
new (&p) std::string("New word");

Создает ли это новое распределение кучи? или он просто заменяет статическую переменную? Чем он отличается от следующего?

p = std::string("New word");
p = new std::string("New word");

РЕДАКТИРОВАТЬ: Спасибо, ребята. Да, кажется, это место новое.

c++
0
Harindu Dilshan 24 Июн 2017 в 00:16
5
Вопрос станет более понятным, если вы опубликуете определение p.
 – 
R Sahu
24 Июн 2017 в 00:17
1
 – 
Mooing Duck
24 Июн 2017 в 00:19
Возможно, это обман stackoverflow.com/q/13370935/10077, хотя я не решаюсь забить его.
 – 
Fred Larson
24 Июн 2017 в 00:20
2
Похоже размещение новое
 – 
AndersK
24 Июн 2017 в 00:20
1
Первый код - это неопределенное поведение (если у объекта есть деструктор, который что-то делает, вы не можете разместить новое поверх него, не вызвав сначала деструктор). Второй не компилируется
 – 
M.M
24 Июн 2017 в 01:05

1 ответ

Лучший ответ
  • new (&p) std::string("New word"); использует новое место размещения . &p должен указывать на уже существующий блок памяти размером не менее sizeof(std::string) байтов. Объект std::string будет построен внутри этой памяти, а не во вновь выделенном блоке памяти. Объект должен быть уничтожен прямым вызовом его деструктора, когда вы закончите его использовать, например:

    char buffer[sizeof(std::string)];
    std::string *p = new (buffer) std::string("New word");
    ...
    p->~std::string();
    
  • p = std::string("New word"); может делать разные вещи в зависимости от контекста, в котором он используется:

    • если используется в операторе объявления переменной, p выделяется в стековой (автоматически) или динамической (динамической) памяти (в зависимости от контекста) и создается копированием с использованием значения std::string :

        some_type p = std :: string ("Новое слово");  //  // такой же как:  // some_type p (std :: string ("Новое слово"));  //  // если some_type = std :: string, то же самое, что:  // std :: string p ("Новое слово");  ...   
    • если используется в операторе присваивания для уже существующего объекта, он выделяет блок временной стековой (автоматической) памяти, создает новый временный объект std::string в этой памяти, присваивая этот временный объект на p, а затем уничтожить временный объект и освободить временную память.

  • p = new std::string("New word"); выделяет новый блок динамической памяти, конструирует в этой памяти объект std::string и затем назначает адрес памяти указателю p. Объект необходимо уничтожить вручную с помощью delete:

    std::string *p = new std::string("New word");
    ...
    delete p;
    

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

2
Remy Lebeau 24 Июн 2017 в 01:13
А как насчет p = std::string("New word");, который не инициализирует новую переменную?
 – 
Barmar
24 Июн 2017 в 01:01
Единственный способ компиляции - это если p является фактическим объектом std::string (или объектом с operator=, который принимает std::string в качестве входных данных), а не std::string* указатель на объект.
 – 
Remy Lebeau
24 Июн 2017 в 01:02
Вот о чем я спрашиваю, например std::string p; ...; p = std::string("New word");. Создает ли это временную строку и копирует ее, или copy elision обходит это?
 – 
Barmar
24 Июн 2017 в 01:04
В вашем первом примере это может произойти из-за того, что буфер символов не выровнен для std :: string (это то, для чего предназначен std::aligned_storage)
 – 
M.M
24 Июн 2017 в 01:08
@Barmar: std::string p; ...; p = std::string("New word"); на самом деле std::string p; ...; p.operator=(std::string("New word")); Создает временный объект и передает его в p, который затем копирует данные.
 – 
Remy Lebeau
24 Июн 2017 в 01:15