如何在 c++ 中为分配的动态对象数组中的所有对象调用参数化构造函数?

How can i call the parameterized constructor for all objects in my dynamic array of objects on allocation in c++?

提问人:Mustafa Muhammad 提问时间:5/3/2022 最后编辑:Nicol BolasMustafa Muhammad 更新时间:10/2/2022 访问量:437

问:

当我定义对象的动态数组时,我想为数组中的所有对象选择一个参数化构造函数。而不必像这样为每个对象编写所选构造函数

#include <iostream>

using namespace std;


class foo {
public:
    foo ()
    { 
        cout << "default constructor" << endl;
    }


    foo (int x)
    {
        cout << "parameterized constructor " << endl;
    }

    ~foo ()
    {
        cout << "destructor" << endl;
    }
};


int main (void)
{
    int size = 3, parameter = 10;
    foo *array;
    array = new foo [size] { foo(parameter), foo(parameter), foo(parameter) };

    cout << endl;

    delete [] array;
    return 0;
}

输出

parameterized constructor 
parameterized constructor 
parameterized constructor 

destructor
destructor
destructor

因此,从上面的代码中可以看出,我可以为数组中的每个对象选择参数化构造函数。 但是,如果用户输入 .同样的伎俩行不通array = new foo [size] { foo(parameter), foo(parameter), foo(parameter) };size

当我搜索解决方案时,我发现我可以像这样使用复制构造函数来做到这一点

#include <iostream>

using namespace std;


class foo {
public:
    foo ()
    { 
        cout << "default constructor" << endl;
    }


    foo (int x)
    {
        cout << "parameterized constructor " << endl;
    }

    ~foo ()
    {
        cout << "destructor" << endl;
    }
};


int main (void)
{
    int size = 3, parameter = 10;
    foo *array;
    array = new foo [size];

    cout << endl;

    for (int i = 0; i < size; i++)
        array[i] = foo(parameter);

    cout << endl;
    
    delete [] array;
    return 0;
}

输出

default constructor
default constructor
default constructor

parameterized constructor 
destructor
parameterized constructor 
destructor
parameterized constructor 
destructor

destructor
destructor
destructor

但是,每个对象都会调用析构函数,我不想要这个 我只想在第一次分配时这样做

提前致谢,我希望有一个解决方案。

C++ 数组 复制构造函数 dynamic-arrays

评论

3赞 Daniel Langr 5/3/2022
解决方案与用途相同。首先,分配存储,然后初始化其中的对象。对于表达式的数组形式,只能应用 value-/default-initialization:en.cppreference.com/w/cpp/language/newstd::vectornew

答:

-3赞 Irog_Nos 5/3/2022 #1

我会使用一个循环:for

array = new foo [size];
for(int i = 0; i < size; i++) {
   array[i] = foo(parameter);
}

我没有看到更简单的方法。使用这种方法,可以很容易地进行参数化。size

对于您的“析构函数问题”,请使用 foo 上的指针:

array = new *foo[size];
for(int i = 0; i < size; i++) {
   array[i] = new foo(parameter);
}

但不要忘记在需要时删除每个实例:foo

for(int i = 0; i < size i++) {
   delete array[i];
}
delete[] array;

评论

1赞 463035818_is_not_an_ai 5/3/2022
OP 已经在使用循环。我看不出这与 OP 代码有什么不同,除了 OP 代码中不存在的越界错误。此代码调用未定义的行为
1赞 463035818_is_not_an_ai 5/3/2022
“对于您的”析构函数问题“,请使用 foo 上的指针”?!?为什么要添加更多指针?你又重复了几次越界
0赞 Irog_Nos 5/3/2022
使用指针是为了避免多次分配和销毁。对不起,我编辑了答案以修复它 X/。
0赞 UnholySheep 5/3/2022
“使用指针是为了避免多次分配和破坏”——但这正是你正在做的——你比常规数组有更多的分配(和处理)。
1赞 Mustafa Muhammad 5/4/2022
@Irog_Nos您的解决方案也很有帮助,谢谢,但是编辑您的主要工作c++ int main (void) { int size = 3, parameter = 10; foo **array; array = new foo *[size]; for(int i = 0; i < size; i++) { array[i] = new foo(parameter); } cout << endl; for (int i = 0; i < size; i++) delete array[i]; return 0; }
2赞 UnholySheep 5/3/2022 #2

这个问题最简单的解决方案是使用 它在内部处理所有这些问题,例如:std::vector

#include <vector>
// skipping class declaration for brevity
int main (void)
{
    int size = 3, parameter = 10;
    std::vector<foo> array;
    array.reserve(size);

    cout << endl;

    for (int i = 0; i < size; i++)
        array.emplace_back(parameter);

    cout << endl;

    return 0;
}

但是,如果出于某种原因您想要/需要手动执行此操作,那么您应该分配一个“原始缓冲区”并在该缓冲区内构造带有放置的对象 - 但是,这也需要您手动调用析构函数new

一个可能的例子,“手动”执行所有操作可能如下所示

int main (void)
{
    int size = 3, parameter = 10;
    foo *array = reinterpret_cast<foo*>(new char[size * sizeof(foo)]);

    cout << endl;

    for (int i = 0; i < size; i++)
        new (&array[i]) foo(parameter);

    cout << endl;

    for (int i = 0; i < size; i++)
        array[i].~foo();

    delete[] reinterpret_cast<char*>(array);
    return 0;
}

一个可以说更干净的解决方案是使用 - 这看起来像这样std::allocatorstd::allocator_traits

#include <memory>
// skipping class declaration
int main (void)
{
    std::allocator<foo> alloc;
    using alloc_t = std::allocator_traits<decltype(alloc)>;
    int size = 3, parameter = 10;
    foo *array;
    array = alloc_t::allocate(alloc, size);

    cout << endl;

    for (int i = 0; i < size; i++)
        alloc_t::construct(alloc, &array[i], parameter);

    cout << endl;

    for (int i = 0; i < size; i++)
        alloc_t::destroy(alloc, &array[i]);
    
    alloc_t::deallocate(alloc, array, size);
    return 0;
}