#c #std
#c #std
Вопрос:
Может кто-нибудь помочь мне понять, почему это не работает?
#include <vector>
#include <algorithm>
using namespace std;
struct person {
int age;
char name[30];
};
int main()
{
vector<person> persons(2);
vector<char*> names(2);
persons[0].age = 1;
strcpy_s(persons[0].name, "mike");
persons[1].age = 11;
strcpy_s(persons[1].name, "pol");
transform(persons.begin(), persons.end(), names.begin(),
[](person p) -> char* {return p.name; });
// ... names gets the same wrong pointer for both elements
}
[Отредактировано, чтобы удалить ненужные неправильные догадки]
Комментарии:
1. Этот код не компилируется. strcpy_s принимает 3 аргумента, но 2 заданы.
2. Проблема не только
strcpy_s
в этом . Все современные компиляторы C достаточно умны, чтобы сказать вам, в чем заключается основная ошибка в показанном коде. Это пример того, как никогда не игнорировать сообщения от вашего компилятора. Даже если ему удается скомпилировать показанный код, предупреждающие сообщения почти всегда являются гарантией того, что у вас ошибка. Обратите внимание на предупреждающее сообщение вашего компилятора.4. Когда вы пишете C , используйте функции C и не используйте код, как если бы это был код C. В этом случае используйте
std::string
.5. Это прискорбно. gcc выдает очень понятное «предупреждение: возвращен адрес локальной переменной ‘p’», в чем и заключается проблема, как описано в ответе.
Ответ №1:
В этом лямбда-выражении:
[](person p) -> char* { return p.name; });
вы создаете копию каждого элемента в persons
, а затем возвращаете указатель на элемент копии. Это зависает, как только вы возвращаетесь из лямбда-выражения, вызывая неопределенное поведение при последующем использовании указателя..
Вместо этого вы могли бы вернуть указатель на элемент ссылки:
[](person amp; p) -> char* { return p.name; });
// ^
Эти указатели действительны до тех пор, пока persons
указывают на одну и ту же базовую память. Изменение persons
таким образом, что указатели на него становятся недействительными, очевидно, приведет к аннулированию указателей names
.