C++,是否可以直接调用构造函数,而不需要new?

发布于 2024-08-26 15:31:32 字数 510 浏览 5 评论 0原文

如果我已经有对象的内存,我可以显式调用构造函数而不使用 new 吗?

class Object1{
    char *str;
public:
    Object1(char*str1){
        str=strdup(str1);
        puts("ctor");
        puts(str);
    }
    ~Object1(){
        puts("dtor");
        puts(str);
        free(str);
    }
};

Object1 ooo[2] = {
     Object1("I'm the first object"), Object1("I'm the 2nd")
};

do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
ooo[0].Object1("I'm the 3rd object in place of first"); // ???? - reuse memory

Can I call constructor explicitly, without using new, if I already have a memory for object?

class Object1{
    char *str;
public:
    Object1(char*str1){
        str=strdup(str1);
        puts("ctor");
        puts(str);
    }
    ~Object1(){
        puts("dtor");
        puts(str);
        free(str);
    }
};

Object1 ooo[2] = {
     Object1("I'm the first object"), Object1("I'm the 2nd")
};

do_smth_useful(ooo);
ooo[0].~Object1(); // call destructor
ooo[0].Object1("I'm the 3rd object in place of first"); // ???? - reuse memory

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

逆光下的微笑 2024-09-02 15:31:32

有点像。您可以使用 placement new 使用已分配的内存运行构造函数:

 #include <new>

 Object1 ooo[2] = {Object1("I'm the first object"), Object1("I'm the 2nd")};
 do_smth_useful(ooo);
 ooo[0].~Object1(); // call destructor

 new (&ooo[0]) Object1("I'm the 3rd object in place of first");

所以,您仍然使用 new 关键字,但不进行内存分配。

Sort of. You can use placement new to run the constructor using already-allocated memory:

 #include <new>

 Object1 ooo[2] = {Object1("I'm the first object"), Object1("I'm the 2nd")};
 do_smth_useful(ooo);
 ooo[0].~Object1(); // call destructor

 new (&ooo[0]) Object1("I'm the 3rd object in place of first");

So, you're still using the new keyword, but no memory allocation takes place.

星星的轨迹 2024-09-02 15:31:32

让我向您展示一些关于如何在构造和销毁过程中完成此操作的代码,

#include <new>

// Let's create some memory where we will construct the object.
MyObject* obj = (MyObject*)malloc(sizeof(MyObject));

// Let's construct the object using the placement new
new(obj) MyObject();

// Let's destruct it now
obj->~MyObject();

// Let's release the memory we used before
free(obj);
obj = 0;

我希望上面的摘要使事情变得更清楚。

Let me show you some code on how it can be done, both in construction and destruction

#include <new>

// Let's create some memory where we will construct the object.
MyObject* obj = (MyObject*)malloc(sizeof(MyObject));

// Let's construct the object using the placement new
new(obj) MyObject();

// Let's destruct it now
obj->~MyObject();

// Let's release the memory we used before
free(obj);
obj = 0;

I hope the above summary makes things clearer.

悟红尘 2024-09-02 15:31:32

我认为您正在寻找新的安置。 C++ FAQ Lite 很好地总结了如何做这个。本条目中有一些重要的问题:

  1. 您应该使用 #include 来使用placement new 语法。
  2. 您的内存缓冲区需要与您正在创建的对象正确对齐。
  3. 您的工作是手动调用析构函数。

I think you're looking for Placement New. The C++ FAQ Lite has a good summary of how you do this. There are a few important gotchas from this entry:

  1. You're supposed to #include <new> to use the placement new syntax.
  2. Your memory buffer needs to be properly aligned for the object you are creating.
  3. It's your job to manually call the destructor.
清引 2024-09-02 15:31:32

从字面上讲,不,没有“new”关键字就无法做到这一点。请参阅有关放置 new 的所有答案,了解使用“new”关键字调用构造函数而不实际分配内存的方法。

Literally speaking, NO, you can't do it without the "new" keyword. See all the answers about placement new for the way to use the "new" keyword to call the constructor without actually allocating memory.

似梦非梦 2024-09-02 15:31:32

是的,当您拥有自己分配的缓冲区时,您可以使用新的放置。 Brian Bondy 在相关问题中给出了很好的答复:

“placement new”有什么用途?

Yes, when you've got your own allocated buffer you use placement new. Brian Bondy has a good response here in a related question:

What uses are there for "placement new"?

影子是时光的心 2024-09-02 15:31:32

您可以调用析构函数,但内存不会被回收,并且您的调用将相当于函数调用。您必须记住,析构函数在下面做了两件事:根据您的规范析构对象,并回收内存。由于无论如何都会为堆栈上分配的对象调用 dtor,因此调用它两次可能会导致未定义的行为。

You can call a destructor, but memory will not be reclaimed, and your call will be equivalent to a function call. You have to remember that underneath the destructor does 2 things: destructs object based on your specification, and reclaims the memory. Since you dtor will be called anyway for an object allocated on the stack, calling it twice may result in an undefined behavior.

微凉 2024-09-02 15:31:32

是的,使用placement new - 如上所述,但您可能会考虑使用第二个工厂类来管理存储,即使这意味着复制对象。 memcpy() 对于小对象来说通常很便宜。

Yes, using placement new - as above, but you might consider having a second factory class to manage the storage, even if it means copying an object. memcpy() is generally cheap for small objects.

阳光下慵懒的猫 2024-09-02 15:31:32

您可以使用以下模板

template <typename T, typename... Args>
inline void InitClass(T &t, Args... args)
{
    t.~T();
    new (&t) T(args...);
}

用法:

struct A
{
   A() {}
   A(int i) : a(i) {}
   int a;
} my_value;

InitClass(my_value);
InitClass(my_value, 5);

You can use the following template

template <typename T, typename... Args>
inline void InitClass(T &t, Args... args)
{
    t.~T();
    new (&t) T(args...);
}

usage:

struct A
{
   A() {}
   A(int i) : a(i) {}
   int a;
} my_value;

InitClass(my_value);
InitClass(my_value, 5);
森林迷了鹿 2024-09-02 15:31:32

问题是,通常您需要一个已经存在的对象来调用函数(除非它是静态函数),因此对于构造函数来说,当您想以非标准方式执行此操作时,这有点问题。

以下是如何在现有内存中创建新的类对象而不使用new。这甚至适用于来自 malloc() 的原始内存,前提是您首先 memset() 将内存清零。

#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>

class Str_obj{
public:
  char* str;
  constexpr Str_obj(const Str_obj& obj) = default;
  Str_obj(const char* str1){
    str = strdup(str1);
    puts("ctor");
    puts(str);
  }
  ~Str_obj(){
    puts("dtor");
    puts(str);
    free(str);
    str = nullptr;
  }
  Str_obj& operator = (const Str_obj& obj){
    puts("copy assign");
    free(str);
    str = strdup(obj.str);
    return *this;
  }
  Str_obj& operator = (Str_obj&& obj){
    puts("move assign");
    free(str);
    str = obj.str;
    obj.str = nullptr;
    return *this;
  }
};

std::vector<std::string>
to_string_vec(Str_obj* arr, size_t len){
  std::vector<std::string> str_arr(len);
  for(int i = 0; i < len; ++i){
    str_arr[i] = std::string(arr[i].str);
  }
  return str_arr;
}

int main() {
  std::cout<<"Creating objects:\n";
  constexpr size_t len = 2;
  Str_obj arr[len] = {
    Str_obj("I'm the first object"),
    Str_obj("I'm the 2nd")
  };
  std::vector<std::string> str_arr1 = to_string_vec(arr, len);

  std::cout<<"\n";
  std::cout<<"Destruct and replace object:\n";
  arr[0].~Str_obj(); // call destructor

  // Calls constructor, then move assign to existing memory.
  arr[0] = std::move(Str_obj("I'm the 3rd object in place of first"));
  std::vector<std::string> str_arr2 = to_string_vec(arr, len);

  std::cout<<"\n";
  for(int i = 0; i < len; ++i){
    std::cout<<i<<". "<<str_arr1[i]<<"\n";
  }
  std::cout<<"\n";
  for(int i = 0; i < len; ++i){
    std::cout<<i<<". "<<str_arr2[i]<<"\n";
  }
  return 0;
}

可能的输出:

Creating objects:
ctor
I'm the first object
ctor
I'm the 2nd

Destruct and replace object:
dtor
I'm the first object
ctor
I'm the 3rd object in place of first
move assign
dtor

0. I'm the first object
1. I'm the 2nd

0. I'm the 3rd object in place of first
1. I'm the 2nd
dtor
I'm the 2nd
dtor
I'm the 3rd object in place of first

The problem is that normally you need an already existing object on which to call the functions (unless it is a static function), so for the constructor that's a bit of a an issue when you want to do it in a nonstandard way.

Here's how to create a new class object in existing memory without using new. This will even work with raw memory from malloc(), provided you first memset() the memory to zeros.

#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>

class Str_obj{
public:
  char* str;
  constexpr Str_obj(const Str_obj& obj) = default;
  Str_obj(const char* str1){
    str = strdup(str1);
    puts("ctor");
    puts(str);
  }
  ~Str_obj(){
    puts("dtor");
    puts(str);
    free(str);
    str = nullptr;
  }
  Str_obj& operator = (const Str_obj& obj){
    puts("copy assign");
    free(str);
    str = strdup(obj.str);
    return *this;
  }
  Str_obj& operator = (Str_obj&& obj){
    puts("move assign");
    free(str);
    str = obj.str;
    obj.str = nullptr;
    return *this;
  }
};

std::vector<std::string>
to_string_vec(Str_obj* arr, size_t len){
  std::vector<std::string> str_arr(len);
  for(int i = 0; i < len; ++i){
    str_arr[i] = std::string(arr[i].str);
  }
  return str_arr;
}

int main() {
  std::cout<<"Creating objects:\n";
  constexpr size_t len = 2;
  Str_obj arr[len] = {
    Str_obj("I'm the first object"),
    Str_obj("I'm the 2nd")
  };
  std::vector<std::string> str_arr1 = to_string_vec(arr, len);

  std::cout<<"\n";
  std::cout<<"Destruct and replace object:\n";
  arr[0].~Str_obj(); // call destructor

  // Calls constructor, then move assign to existing memory.
  arr[0] = std::move(Str_obj("I'm the 3rd object in place of first"));
  std::vector<std::string> str_arr2 = to_string_vec(arr, len);

  std::cout<<"\n";
  for(int i = 0; i < len; ++i){
    std::cout<<i<<". "<<str_arr1[i]<<"\n";
  }
  std::cout<<"\n";
  for(int i = 0; i < len; ++i){
    std::cout<<i<<". "<<str_arr2[i]<<"\n";
  }
  return 0;
}

Possible output:

Creating objects:
ctor
I'm the first object
ctor
I'm the 2nd

Destruct and replace object:
dtor
I'm the first object
ctor
I'm the 3rd object in place of first
move assign
dtor

0. I'm the first object
1. I'm the 2nd

0. I'm the 3rd object in place of first
1. I'm the 2nd
dtor
I'm the 2nd
dtor
I'm the 3rd object in place of first
拥有 2024-09-02 15:31:32

根据评论,这仅适用于 Microsoft C++ 编译器

非常简单,没有 new

    imguistate = (int *)malloc(ImGui::GetInternalStateSize());
    memset(imguistate, 0, ImGui::GetInternalStateSize());
    ((ImGuiState *)imguistate)->ImGuiState::ImGuiState();

这适用于任何类:

class SomeClass {
public:
    SomeClass() {
        printf("Called constructor\n");
    }
};

int main () {
    SomeClass *someclass = new SomeClass;
    someclass->SomeClass::SomeClass(); // call constructor again
}

Based on comments, this only works for Microsoft C++ compilers

Quite simply, without new:

    imguistate = (int *)malloc(ImGui::GetInternalStateSize());
    memset(imguistate, 0, ImGui::GetInternalStateSize());
    ((ImGuiState *)imguistate)->ImGuiState::ImGuiState();

This works with any class:

class SomeClass {
public:
    SomeClass() {
        printf("Called constructor\n");
    }
};

int main () {
    SomeClass *someclass = new SomeClass;
    someclass->SomeClass::SomeClass(); // call constructor again
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文