Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 30.11.20 08:41
Оценка: :)
Добрый день. Подскажите как правильно сделать?
Мне нужно заполнять несколько массивов в одном классе и передать их в другой (там в отдельном потоке их обрабатывать, а потом удалять). Я по старинке делал так (очень примеренный псевдокод):
#include <iostream>

struct Aaa
{
    char sz[32];
    int a;
};

class cl2
{
public:
    void Foo2(uint8_t* ptr, int nCnt)
    {
        Aaa* pCurAaa = (Aaa*)ptr;
        for (int i = 0; i < nCnt; i++)
        {
            std::cout << pCurAaa->sz << "\t" << pCurAaa->a << std::endl;
            pCurAaa++;
        }
        std::cout << std::endl;
        
        // освобождаем память
        delete[] ptr;
    }
};
cl2 c2;

class cl1
{
public:
    uint8_t *m_pAaa;

    void Foo1()
    {
        // несколько раз заполняем
        for (int i = 0; i < 5; i++)
        {
            int nCnt = 10 + i;
            int nSize = sizeof(Aaa) * nCnt;
            m_pAaa = new uint8_t[nSize];
            memset(m_pAaa, 0, nSize);
            Aaa* pCurAaa = (Aaa*)m_pAaa;

            for (int j = 0; j < nCnt; j++)
            {
                strcpy_s(pCurAaa->sz, "text");
                pCurAaa->a = j;
                pCurAaa++; // shift to the next item
            }

            // передаём в другой класс
            c2.Foo2(m_pAaa, nCnt);
            m_pAaa = NULL; // всё, тут "забываем" про этот кусок памяти, с ним работает и потом удаляет касс2
        }
    }
};

void main()
{
    cl1 c1;
    c1.Foo1();
}

Так вот, вроде как нужно использовать std::vector(), чтобы например не тащить за собой размер передаваемого массива ну и вроде как безопаснее, так?
Если да, то как переписать подобное на использование std::vector()...
PS. И еще один вопрос, а как мне добавить в мою структуру Aaa переменную с типом std::string?
ЗЫЫ. в реальном коде uint8_t *m_pAaa; в классе1 тоже нужна, т.е. с ней работают методы класса1 пока не передали в класс2
Re: Передать массив структур из одного класса в другой
От: SaZ  
Дата: 30.11.20 12:32
Оценка:
Здравствуйте, .alex, Вы писали:

A>Добрый день. Подскажите как правильно сделать?

A>Мне нужно заполнять несколько массивов в одном классе и передать их в другой (там в отдельном потоке их обрабатывать, а потом удалять). Я по старинке делал так (очень примеренный псевдокод):

Нужно почитать что-нибудь по основам языка программирования, на котором вы пишите.

A>Так вот, вроде как нужно использовать std::vector(), чтобы например не тащить за собой размер передаваемого массива ну и вроде как безопаснее, так?


Так удобнее в большинстве случаев.

A>Если да, то как переписать подобное на использование std::vector()...


Что именно у вас не получается?

A>PS. И еще один вопрос, а как мне добавить в мою структуру Aaa переменную с типом std::string?


Точно так же, как и любую другую переменную.

A>ЗЫЫ. в реальном коде uint8_t *m_pAaa; в классе1 тоже нужна, т.е. с ней работают методы класса1 пока не передали в класс2


Не используйте сырые указатели вообще. Они в 99% случаев не нужны. Используйте умные указатели, хотя-бы тот же std::shared_ptr. Примеров в интернете хватает, но стоит разобраться как именно они работают.
Re: Передать массив структур из одного класса в другой
От: B0FEE664  
Дата: 30.11.20 12:58
Оценка:
Здравствуйте, .alex, Вы писали:

A>Мне нужно заполнять несколько массивов в одном классе и передать их в другой (там в отдельном потоке их обрабатывать, а потом удалять). Я по старинке делал так (очень примеренный псевдокод):

A>Так вот, вроде как нужно использовать std::vector(), чтобы например не тащить за собой размер передаваемого массива ну и вроде как безопаснее, так?
std::vector следует использовать там, где вы заранее не знаете размер массива. Если размер фиксированный и заранее известный, то std::array.
Однако, похоже, что вы передаёте текст, а тогда следует использовать std::string.

A>Если да, то как переписать подобное на использование std::vector()...

Это можно сделать разными способами...
Если переписывать то, что вы делаете (не меняя архитектуры), то, наверно, лучше всего будет использование std::unique_ptr< std::string >

A>PS. И еще один вопрос, а как мне добавить в мою структуру Aaa переменную с типом std::string?

struct Aaa
{
    char sz[32];
    int a;
    std::string value;
};




A>ЗЫЫ. в реальном коде uint8_t *m_pAaa; в классе1 тоже нужна, т.е. с ней работают методы класса1 пока не передали в класс2

Если вам нужно передать массив структур, то можно воспользоваться типом std::unique_ptr< std::vector<Aaa> >


Прежде чем давать более точные советы нужно знать:
— на какой уровень знания C++ следует ориентироваться;
— требования по скорости выполнения;
— какой стандарт C++ доступен для использования;
— природа задачи: потоковая обработка или распараллеливание счётной задачи;
и т.д..
И каждый день — без права на ошибку...
Re: Передать массив структур из одного класса в другой
От: a7d3  
Дата: 30.11.20 14:11
Оценка:
Здравствуйте, .alex, Вы писали:

A>Добрый день. Подскажите как правильно сделать?


Стандарт какой, C++11 годится?

A>PS. И еще один вопрос, а как мне добавить в мою структуру Aaa переменную с типом std::string?


Вся структура Aaa — это тупо аналог std::string, может от неё просто избавиться?
32-байта как раз и есть Small String Optimization (SSO) в современных С++ на 64-битных платформах. Когда при коротких строках указатель на буфер с текстом и переменная с длинной этого буфера по прямому назначению не используются, а в себе хранят текст длинной до 32-х байт. Это стало частью стандартного С++, после того как с этим давно играли на разные лады https://www.ibm.com/support/pages/small-string-optimized-sso-string-class
Re[2]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 30.11.20 17:09
Оценка:
A>Стандарт какой, C++11 годится?
Конечно годится...

A>Вся структура Aaa — это тупо аналог std::string, может от неё просто избавиться?

A>32-байта как раз и есть Small String Optimization (SSO) в современных С++ на 64-битных платформах. Когда при коротких строках указатель на буфер с текстом и переменная с длинной этого буфера по прямому назначению не используются, а в себе хранят текст длинной до 32-х байт. Это стало частью стандартного С++, после того как с этим давно играли на разные лады https://www.ibm.com/support/pages/small-string-optimized-sso-string-class
Не, в реальности структура большая, и даже это не структура а класс, там несколько методов и куча других переменных...
Re[2]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 30.11.20 17:19
Оценка:
Здравствуйте, B0FEE664, Вы писали:
BFE>std::vector следует использовать там, где вы заранее не знаете размер массива. Если размер фиксированный и заранее известный, то std::array.
BFE>Однако, похоже, что вы передаёте текст, а тогда следует использовать std::string.
кол-во элементов я заранее не знаю...

A>>Если да, то как переписать подобное на использование std::vector()...

BFE>Это можно сделать разными способами...
BFE>Если переписывать то, что вы делаете (не меняя архитектуры), то, наверно, лучше всего будет использование std::unique_ptr< std::string >
Почитаю про std::unique_ptr...

BFE> — на какой уровень знания C++ следует ориентироваться;

мой уровень это "С с классами" )), т.е. совсем не высокий...

BFE> — требования по скорости выполнения;

желательно очень быстро, на С и обычными plain массивами все получается очень шустро, но хочется немного компромисса в части скорости написания кода...

BFE> — какой стандарт C++ доступен для использования;

я сварщик не настоящий, для развлечения поставил в настройках студии 17 стандарт, чтобы работали конструкции типа if (int random_num = rand(); random_num % 2 == 0) и еще пользую что-то типа for(v: MyVec), но больше особо стандарты не различаю...

BFE> — природа задачи: потоковая обработка или распараллеливание счётной задачи;

вкратце, получение одним потоком рекордсетов из БД, вторым — обработка этих рекордсетов и файловый ввод-вывод...
Re[2]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 30.11.20 17:23
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Нужно почитать что-нибудь по основам языка программирования, на котором вы пишите.

я как понимаю надо про std::unique_ptr и std::shared_ptr почитать, верно?

A>>Если да, то как переписать подобное на использование std::vector()...


SaZ>Что именно у вас не получается?

Нет понимания как сделать указатель на вектор, чтобы его потом передать в другой класс без копирования данных и потом обнулить указатель в первом классе и опять выделать место для нового вектора...
Что я пытался в своем псевдокоде изобразить... std::vector<Acc> *pVec = new... вот что дальше, чтобы конструкторы все вызвались ну пр...
Да и объясняю я наверно не шибко понятно... Наверно у меня представления несколько старые... из С...
Re[3]: Передать массив структур из одного класса в другой
От: a7d3  
Дата: 01.12.20 01:50
Оценка:
Здравствуйте, .alex, Вы писали:

A>Не, в реальности структура большая, и даже это не структура а класс, там несколько методов и куча других переменных...


Заполнять вектор можно через https://en.cppreference.com/w/cpp/container/vector/emplace
Если у этой структуры-класса есть конструктор с аргументами, то они передаются в std::vector::emplace, внутри которого и вызовется уже создание класса (внутри heap, т.е. через new).
Соответственно, деструктор std::vector очистит за собой всю память (в которой создавал экземпляры Aaa). Это же самое сделает и в случае вызова std::vector::clear();


struct Aaa
{
    char sz[32];
    int a;

    Aaa(const char* sz_, int a ) : sz(sz_), a(a_)
    {}
};

class cl2
{
public:
    void Foo2(const std::vector<Aaa>& arr)
    {
        for (const auto& curAaa : arr)
        {
            std::cout << curAaa.sz << "\t"
                      << curAaa.a << std::endl;
        }
        std::cout << std::endl;
    }
};

class cl1
{
public:
    void Foo1()
    {
        std::vector<Aaa> arr;

        arr.reserve(5); // не обязательно, но полезно
 
        for (int i = 0; i < 5; i++)
        {
            for (int j = 0; j < nCnt; j++)
            {
                arr.emplace( arr.end(), "text", j );
            }

            c2.Foo2( arr );
            arr.clear();        
        }
    }
};


Условно, вызов std::vector::reserve() выделит память в heap заранее без инициализации, чтобы не дёргать new во время каждого emplace. На пяти элементах это фигня, а вот на десятках элементов оно полезно.
Re[4]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 01.12.20 09:39
Оценка:
Здравствуйте, a7d3, Вы писали:

A>Заполнять вектор можно через https://en.cppreference.com/w/cpp/container/vector/emplace

A>Если у этой структуры-класса есть конструктор с аргументами, то они передаются в std::vector::emplace, внутри которого и вызовется уже создание класса (внутри heap, т.е. через new).
A>Соответственно, деструктор std::vector очистит за собой всю память (в которой создавал экземпляры Aaa). Это же самое сделает и в случае вызова std::vector::clear();

A>

A>struct Aaa
A>{
A>    char sz[32];
A>    int a;

A>    Aaa(const char* sz_, int a ) : sz(sz_), a(a_)
A>    {}
A>};

A>class cl2
A>{
A>public:
A>    void Foo2(const std::vector<Aaa>& arr)
A>    {
A>        for (const auto& curAaa : arr)
A>        {
A>            std::cout << curAaa.sz << "\t"
A>                      << curAaa.a << std::endl;
A>        }
A>        std::cout << std::endl;
A>    }
A>};

A>class cl1
A>{
A>public:
A>    void Foo1()
A>    {
A>        std::vector<Aaa> arr;

A>        arr.reserve(5); // не обязательно, но полезно
 
A>        for (int i = 0; i < 5; i++)
A>        {
A>            for (int j = 0; j < nCnt; j++)
A>            {
A>                arr.emplace( arr.end(), "text", j );
A>            }

A>            c2.Foo2( arr );
A>            arr.clear();        
A>        }
A>    }
A>};

A>


A>Условно, вызов std::vector::reserve() выделит память в heap заранее без инициализации, чтобы не дёргать new во время каждого emplace. На пяти элементах это фигня, а вот на десятках элементов оно полезно.

Спасибо!
Да, про reserve() в курсе конечно, чтобы переаллокаций не было...
Но я хотел немного не то...
Идея была в том что в Классе1 хранится только указатель на кусок памяти/вектор...
Т.е. я в Класс1::Foo() выделил память, и этот указатель на неё теперь указывает, потом в классе1 я заполнил этот кусок памяти/вектор, еще какие-то методы Класса1 с ним поработали (в реальности его отображает виртуальный CListCtrl через GetDispInfo()), потом нажали кнопку и я просто передаю этот указатель в другой класс2 и уже он начинает работать с этим куском памяти/вектором. А в классе1 я опять выделяю новую память и указатель Класса1 уже указывает на него(новый кусок), заполняю/работаю/передаю и так несколько раз...
Re[5]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 02.12.20 07:17
Оценка:
Здравствуйте, .alex, Вы писали:
A>Идея была в том что в Классе1 хранится только указатель на кусок памяти/вектор...
A>Т.е. я в Класс1::Foo() выделил память, и этот указатель на неё теперь указывает, потом в классе1 я заполнил этот кусок памяти/вектор, еще какие-то методы Класса1 с ним поработали (в реальности его отображает виртуальный CListCtrl через GetDispInfo()), потом нажали кнопку и я просто передаю этот указатель в другой класс2 и уже он начинает работать с этим куском памяти/вектором. А в классе1 я опять выделяю новую память и указатель Класса1 уже указывает на него(новый кусок), заполняю/работаю/передаю и так несколько раз...
Я видимо очень сумбурно объяснил? Или просто так не делают?
Re[3]: Передать массив структур из одного класса в другой
От: qaz77  
Дата: 02.12.20 07:34
Оценка:
Здравствуйте, .alex, Вы писали:

A>Нет понимания как сделать указатель на вектор, чтобы его потом передать в другой класс без копирования данных и потом обнулить указатель в первом классе и опять выделать место для нового вектора...

A>Что я пытался в своем псевдокоде изобразить... std::vector<Acc> *pVec = new... вот что дальше, чтобы конструкторы все вызвались ну пр...
A>Да и объясняю я наверно не шибко понятно... Наверно у меня представления несколько старые... из С...

Не надо вектор выделять динамически.
Чтобы дешево перекинуть данные из одного вектора в другой надо использовать move-семантику (С++ 11 и выше) или swap (до C++ 11).

Вариант с move:
void Foo2(std::vector<Aaa>&& arg)
{
   std::vector<Aaa> local = std::move(arg);
   ...
}


Вариант со swap:
void Foo2(std::vector<Aaa>& arg)
{
   std::vector<Aaa> local;
   local.swap(arg);
   ...
}
Re[5]: Передать массив структур из одного класса в другой
От: a7d3  
Дата: 02.12.20 09:28
Оценка: 3 (1)
Здравствуйте, .alex, Вы писали:

A>Т.е. я в Класс1::Foo() выделил память, и этот указатель на неё теперь указывает, потом в классе1 я заполнил этот кусок памяти/вектор, еще какие-то методы Класса1 с ним поработали (в реальности его отображает виртуальный CListCtrl через GetDispInfo()), потом нажали кнопку и я просто передаю этот указатель в другой класс2 и уже он начинает работать с этим куском памяти/вектором. А в классе1 я опять выделяю новую память и указатель Класса1 уже указывает на него(новый кусок), заполняю/работаю/передаю и так несколько раз...



struct Aaa
{
    char sz[32];
    int a;

    Aaa(const char* sz_, int a ) : sz(sz_), a(a_)
    {}
};

using vector_aaa_t = std::vector<Aaa>;
using ptr_set_t = std::shared_ptr< vector_aaa_t >;

class cl2
{
public:
    void Foo2(ptr_set_t arr)
    {
        for (const auto& curAaa : *arr)
        {
            std::cout << curAaa.sz << "\t"
                      << curAaa.a << std::endl;
        }
        std::cout << std::endl;
    }
};

class cl1
{
public:
    void Foo1()
    {
        auto spArr = std::make_shared<vector_aaa_t>();
        spArr->reserve(5);
 
        for (int i = 0; i < 5; i++)
        {
            for (int j = 0; j < nCnt; j++)
            {
                spArr->emplace( arr.end(), "text", j );
            }

            c2.Foo2( spArr );
            spArr->clear();
        }
    }
};
Re: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 03.12.20 07:20
Оценка:
Все спасибо, разобрался. Сделал через emplace и std::move()...
Кстати сравнил с вариантом через new... new, быстрее, но незначительно, а код конечно с векторами более читабельный и лаконичный...
Re[2]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 04.12.20 09:11
Оценка:
Кстати подумал, что все-таки нужно себя проверить... Посмотрите пожалуйста код, так нужно делать, в смысле все ли корректно?
#include <iostream>
#include <vector>

struct Aaa
{
    char sz[32];
    int a;
    std::string s;

    Aaa(const char* sz_, int a_, std::string str) : a(a_), s(str)
    {
        strcpy_s(sz, sz_);
    }
};

class cl2
{
public:
    void Foo2(std::vector<Aaa>& arg)
    {
        std::vector<Aaa> local = std::move(arg);
        for (const auto& a : local)
        {
            std::cout << a.sz << "\t" << a.a << "\t" << a.s << std::endl;
        }
        std::cout << std::endl;
    }
};
cl2 c2;

class cl1
{
public:
    std::vector<Aaa> vAaa;

    void Foo1()
    {
        vAaa.reserve(50);
        for (int i = 0; i < 50; i++)
        {
            int nCnt = 10 + i;

            for (int j = 0; j < nCnt; j++)
            {
                vAaa.emplace(vAaa.end(), "sz", j, "string");
            }
            c2.Foo2(vAaa);
        }
    }
};

void main()
{
    cl1 c1;
    c1.Foo1();
}
Re[3]: Передать массив структур из одного класса в другой
От: qaz77  
Дата: 04.12.20 10:03
Оценка:
Здравствуйте, .alex, Вы писали:

A>Кстати подумал, что все-таки нужно себя проверить... Посмотрите пожалуйста код, так нужно делать, в смысле все ли корректно?

struct Aaa
{
    char sz[32];
    int a;
    std::string s;

    Aaa(const char* sz_, int a_, std::string str) : a(a_), s(str)
    {
        strcpy_s(sz, sz_); // <<< почему не strncpy c sizeof(sz) или вообще std::string использовать?
    }
};

class cl2
{
public:
    void Foo2(std::vector<Aaa>& arg) // <<< если уж внутри std::move, то и тут лучше &&
    {
        std::vector<Aaa> local = std::move(arg);
        for (const auto& a : local)
        {
            std::cout << a.sz << "\t" << a.a << "\t" << a.s << std::endl;
        }
        std::cout << std::endl;
    }
};
cl2 c2;

class cl1
{
public:
    std::vector<Aaa> vAaa;

    void Foo1()
    {
        vAaa.reserve(50); // <<< вот тут уже баг, резерв только для первого вектора (память уедет при первом вызове Foo2)
        for (int i = 0; i < 50; i++)
        {
            int nCnt = 10 + i;

            for (int j = 0; j < nCnt; j++)
            {
                vAaa.emplace(vAaa.end(), "sz", j, "string");  // <<< почему не emplace_back?
            }
            c2.Foo2(vAaa);  // <<< тут использовать std::move(vAaa)
        }
    }
};
Re[4]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 04.12.20 14:59
Оценка:
Q>strcpy_s(sz, sz_); // <<< почему не strncpy c sizeof(sz) или вообще std::string использовать?
тут просто что-то написал, это не реальный код...

Q>void Foo2(std::vector<Aaa>& arg) // <<< если уж внутри std::move, то и тут лучше &&

...
Q>c2.Foo2(vAaa); // <<< тут использовать std::move(vAaa)
А вот про && не знал... Что-то непонятно про эти l/r-value ссылки... Правильно я понял что && это типа const std::vector<Aaa>& arg?
И в чем отличие если писать с2.Foo2(std::move(vAaa))?


Q>vAaa.reserve(50); // <<< вот тут уже баг, резерв только для первого вектора (память уедет при первом вызове Foo2)

Да, ошибся...
Q>vAaa.emplace(vAaa.end(), "sz", j, "string"); // <<< почему не emplace_back?
тоже ошибся

Да, с Си'шными указателями как-то все понятнее — выделил кусок памяти и гоняй его куда хочешь, главное не забыть удалить)
Re[5]: Передать массив структур из одного класса в другой
От: qaz77  
Дата: 04.12.20 15:33
Оценка:
Здравствуйте, .alex, Вы писали:
A>А вот про && не знал... Что-то непонятно про эти l/r-value ссылки... Правильно я понял что && это типа const std::vector<Aaa>& arg?
A>И в чем отличие если писать с2.Foo2(std::move(vAaa))?

Нет, это не const X&.
&& помечает, что объект или временный, или больше не нужен.
std::move помечает, что эта именованная переменная переменная больше не нужна и можно ее кишки переместить в другое место без потери смысла.

Программы пишутся для людей, а не для компилятора.
Когда программист видит в сигнатуре функции &&, то ему становится все понятно, что переданный объект уезжает с концами.

Плохо только в С++ имхо, что в шаблонах && другой смысл имеет...
Re[3]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 07.12.20 15:45
Оценка:
А еще один вопрос вдогонку) Что-то начитался про конструкторы копирования и перемещения и еще больше запутался... теперь все думаю не будет ли лишнего new вызвано)
Может стоит в конструкторе моего класса написать
...
A> Aaa(const char* sz_, int a_, const std::string & str) : a(a_), s(str)
А?
Строка большая и все это вариант без small string optimization...
Re[4]: Передать массив структур из одного класса в другой
От: .alex Ниоткуда  
Дата: 07.12.20 15:47
Оценка:
Здравствуйте, .alex, Вы писали:

A>А еще один вопрос вдогонку) Что-то начитался про конструкторы копирования и перемещения и еще больше запутался... теперь все думаю не будет ли лишнего new вызвано)

A>Может стоит в конструкторе моего класса написать
A>...
A>> Aaa(const char* sz_, int a_, const std::string & str) : a(a_), s(str)
A>А?
A>Строка большая и все это вариант без small string optimization...
Хотя интересен ответ и с маленько строкой (sso)
Re[5]: Передать массив структур из одного класса в другой
От: watchmaker  
Дата: 07.12.20 17:55
Оценка:
Здравствуйте, .alex, Вы писали:

A>Здравствуйте, .alex, Вы писали:


A>>А еще один вопрос вдогонку) Что-то начитался про конструкторы копирования и перемещения и еще больше запутался... теперь все думаю не будет ли лишнего new вызвано)



Сейчас у тебя написано так:

    std::string s;

    Aaa(std::string str) : s(str) ...

В таком коде всегда будет копирование строки в конструкции s(str): будет вызван copy constructor, который сконструирует новую строку и скопирует туда содержимое старой, а потом старая разрушится.
Плюс, есть ещё такой недостаток, что например при вызове Aaa("foobar") сначала сконструируется временная строка в куче, а потом с неё будет сделана копия (с ещё одним выделением памяти).

Чтобы не было одного копирования нужно было написать конструктор так:
Aaa(std::string str) : s(std::move(str)) ...

Тогда, если теперь вызвать Aaa("foobar"), то содержимое временной строки переместится, то есть одно выделение памяти пропадёт.

Соответственно, если у тебя есть уже готовый объект std::string a, то вызов Aaa(a) сначала позовёт copy-constructor, а затем move-constructor. А вызов Aaa(std::move(a)) позовёт два раза move-constructor (один раз чтобы переместить строку из a в параметр конструктора, а второй раз чтобы переместить её оттуда в объект).


Если move-constructor дорогой (а не у всех классов он дёшев), то от него часто бывает полезно избавится, написав два конструктора отдельно для обоих случаев:
Aaa(const std::string& str) : s(str) ...
Aaa(std::string&& str) : s(std::move(str)) ...


Но тут, конечно, видна проблема, что если параметров много, то нужно либо выписывать много конструкторов, либо делать его шаблонным.


A>>Может стоит в конструкторе моего класса написать

A>>...
A>>> Aaa(const char* sz_, int a_, const std::string & str) : a(a_), s(str)
A>>А?

В целом до С++11 так и писали. Но тут всегда будет копирование. Поэтому почти все и использовали copy-on-write реализации строк, в которых копирование в таких ситуациях не приводило к перевыделению памяти, а лишь меняло счётчик ссылок. Если же строка не copy-on-write (а теперь они все такие), то такой код будет не очень хорошим.
Но он станет хорошим, если к нему добавить парный конструктор, принимающий std::string&&, как показано выше.

A>>Строка большая и все это вариант без small string optimization...

A>Хотя интересен ответ и с маленько строкой (sso)

Тебе определённо стоит посмотреть рекомендации по передачи параметров в С++ core guidelines.

Но вывод такой:
Если класс имеет дешёвый move-конструктор, то можно писать так:
Aaa(std::string str) : s(std::move(str))

Если класс имеет дорогой move-конструктор, то лучше писать так:
Aaa(const std::string& str) : s(str) 
Aaa(std::string&& str) : s(std::move(str)) 
// или шаблонный аналог вместо двух вариантов


У std::string move-конструктор не дорогой, но и не совсем тривиальный (как раз из-за необходимости ветвления из-за SSO).
И пока не у всех современных компиляторов ещё хватает ума опитимизировать серии таких перемещений.
Поэтому, из последних двух вариантов оба можно использовать ("лишних" выделений памяти не будет ни в одном, ни в другом), но вариант с двумя конструкторами иногда оказывается на пару наносекунд быстрее, так как в нём компилятору проще понять логику происходящего и не надо генерировать код для промежуточного move-конструктора.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.