#c #std #operator-keyword #stdmap #initializer-list
#c #std #operator-ключевое слово #stdmap #список инициализаторов
Вопрос:
Я использовал список инициализаторов для создания объекта и присвоения его карте с int
помощью ключа. В случае простой структуры временная структура может быть создана с помощью списка инициализаторов.
следовательно, я делаю что-то подобное, что абсолютно допустимо
struct fileJobPair {
int file;
int job;
};
map<int, fileJobPair> mp;
mp[1] = {10, 20};
mp[2] = {100, 200};
mp[3] = {1000, 2000};
Но если я добавлю конструктор в структуру, я получаю сообщение об ошибке
file.cpp: In function ‘int main()’:
file.cpp:18:21: error: no match for ‘operator=’ (operand types are ‘std::map<int, fileJobPair>::mapped_type’ {aka ‘fileJobPair’} and ‘<brace-enclosed initializer list>’)
18 | mp[1] = {10, 20};
| ^
file.cpp:4:8: note: candidate: ‘constexpr AfileJobPairamp; AfileJobPair::operator=(const AfileJobPairamp;)’
4 | struct fileJobPair {
| ^~~~~~~~~~~~
file.cpp:4:8: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const fileJobPairamp;’
file.cpp:4:8: note: candidate: ‘constexpr fileJobPairamp; fileJobPair::operator=(fileJobPairamp;amp;)’
file.cpp:4:8: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘fileJobPairamp;amp;’
Это то, что я пробовал :
struct fileJobPair {
int file;
int job;
fileJobPair()
{
file = job = 0;
}
};
int main()
{
map<int, fileJobPair> mp;
mp[1] = {10, 20};
mp[2] = {100, 200};
mp[3] = {1000, 2000};
for(int i =1;i<=3;i )
{
cout<< mp[i].file <<" "<< mp[i].job<<endl;
}
return 0;
}
Почему я получаю ошибку и как именно она работает внутри?
Комментарии:
1.
fileJobPair
имеет конструктор по умолчанию, поэтому вы не можете использовать инициализаторы для его инициализации2. Эта проблема возникает только тогда, когда я добавляю конструктор в эту простую структуру. ТАК точно ли это работает внутри
3. Это не проблема
map
. Вы получите то же самое сfileJobPair f; f = {10,20};
. Разница в том, что после добавления пользовательского конструктора по умолчаниюfileJobPair
он больше не является агрегатом . Подробности смотрите здесь: en.cppreference.com/w/cpp/language/aggregate_initialization .4. @DanielLangr большое спасибо, это прояснило мою концепцию. Пожалуйста, напишите ответ на него, и я приму то же самое
5. @DanielLangr разве ответ riquefr не делает недействительным все, что говорится в документации? «нет объявленных пользователем конструкторов»
Ответ №1:
Когда вы создаете новый fileJobPair
, он будет использовать по умолчанию ваш пустой конструктор, поэтому он больше не будет доступен для завершения {}
. Но вы можете добавить к нему новый конструктор, который получает 2 целых числа и привязывает их к соответствующим значениям, например:
#include <iostream>
#include <map>
using namespace std;
struct fileJobPair {
int file;
int job;
fileJobPair() {
file = job = 0;
}
fileJobPair(int a, int b) {
file = a;
job = b;
}
};
int main()
{
map<int, fileJobPair> mp;
mp[1] = {10,10};
mp[2] = {100, 200};
mp[3] = {1000, 2000};
for(int i =1;i<=3;i )
{
cout<< mp[i].file <<" "<< mp[i].job<<endl;
}
return 0;
}
Комментарии:
1. о, но как это работает, когда в документации говорится
no user-declared constructors no user-provided constructors
2. Я не знаю о реализации на языке C , которая это позволяет, но я думаю, это потому, что теперь он знает, что вы можете использовать целочисленное значение 2 для инициализации структуры, когда вы используете пустой конструктор, у него нет возможности узнать это.
Ответ №2:
Согласно документации, вы можете использовать список инициализаторов только тогда, когда ваша структура / класс не содержит
- нет закрытых или защищенных прямых нестатических элементов данных
- нет объявленных пользователем конструкторов
- конструкторы, предоставленные пользователем, отсутствуют (разрешены явно установленные по умолчанию или удаленные конструкторы)
- нет пользовательских, унаследованных или явных конструкторов (разрешены явно установленные по умолчанию или удаленные конструкторы)
- нет объявленных пользователем или унаследованных конструкторов
- нет виртуальных, частных или защищенных базовых классов
- нет виртуальных функций-членов
- нет инициализаторов элементов по умолчанию
И в вашем случае ваша структура имеет конструктор, объявленный пользователем.
Как указано в комментариях OP, ответ @riqefr работает, а в документации указано иное.
Для этого вам нужно понять, что такое агрегат,
Агрегат — это массив или класс без объявленных пользователем конструкторов, без закрытых или защищенных нестатических элементов данных, без базовых классов и виртуальных функций.
Поэтому, когда вы добавили пользовательский конструктор в свою структуру, он больше не остается агрегатом.
Чтобы узнать больше о преимуществах aggregate по сравнению с вашими обычными классами. Пожалуйста, обратитесь https://www.educba.com/c-plus-plus-aggregation /