gpt4 book ai didi

c++ - 从类重载的新运算符运行非默认构造函数

转载 作者:行者123 更新时间:2023-11-28 01:16:25 25 4
gpt4 key购买 nike

我要上课Watchdog在 POSIX 共享内存中创建其对象。

请记住,此类的源代码被编译成静态库,方法的源代码实际上放在 c++ 源文件中。

我的第一次尝试是使用 static Watchdog* createWatchdog(param p1, param p2, ...)我的类中的函数,并将其用作分配对象内存的包装器,然后调用放置 new (ptr) Watchdog .

这很好用,但后来我想起了 new运算符可能会过载,所以我想出了这个解决方案:

Watchdog.h

#pragma once

#include <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

namespace og {

class Watchdog {
public:
Watchdog();
Watchdog(const std::string t_name, void* t_data, const size_t t_datSize);

static void* operator new(size_t count, const std::string t_name, const size_t t_datSize);


protected:
Watchdog(const Watchdog&) = delete;
Watchdog& operator=(const Watchdog&) = delete;

private:
std::string m_name;
void* m_data;
size_t m_datSize;

// and other member variables
}; // end class Watchdog

} // end namespace

Watchdog.cxx

#include "Watchdog.h"

using namespace og;

Watchdog::Watchdog()
{}

Watchdog::Watchdog(const std::string t, void* t_data, const size_t size)
{}

void* operator new(size_t count, const std::string t_name, const size_t dat)
{
int fd;
void* obj;

// removed all error checks for the sake of the example
fd = shm_open(t_name.c_str(), O_CREAT | O_EXCL | O_RDWR, 0600);
(void) ftruncate(fd, sizeof(Watchdog));
obj = mmap(0x0, sizeof(Watchdog), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
(void) shm_unlink(t_name.c_str());

return obj;
}

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
PROJECT( WATCHDOG C CXX )

SET( CMAKE_CXX_STANDARD 11)
SET( CMAKE_CXX_STANDARD_REQUIRED OFF)

SET( watchdog_HEADERS
Watchdog.h
)

SET( watchdog_SRC
Watchdog.cxx
${watchdog_HEADERS}
)

SET( CMAKE_CXX_FLAGS_DEBUG "-g3 -Wall -Wextra -Wpedantic")

ADD_LIBRARY( watchdog STATIC ${watchdog_SRC} )
TARGET_LINK_LIBRARIES( watchdog -lrt )

编译自cmake . && make

main.cxx

#include "Watchdog.h"

using namespace og;

int
main()
{
Watchdog* W;

W = new ("test", 20) Watchdog;
}

  1. 编译g++ main.cxx -L. -lwatchdog -lrt引发链接错误:

/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: /tmp/ccDncNvb.o: in function `main':
main.cxx:(.text+0x3c): undefined reference to `og::Watchdog::operator new(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long)'
collect2: error: ld returned 1 exit status


  1. 我是否必须在 operator new 方法中手动初始化所​​有成员变量?我知道我能做到return ::operator new (sz)return ::operator new(sz, ptr)来自 operator new 方法,但我看不出如何调用非默认构造函数(例如类规范中的第二个构造函数)。

最佳答案

问题一:

你的定义

void* operator new(size_t count, const std::string t_name, const size_t dat) //...

Watchdog.cxx 中定义了一个免费的用户定义的 operator new,而不是您在 Watchdog 类中声明的特定于类的重载>.

改为使用:

void* Watchdog::operator new(size_t count, const std::string t_name, const size_t dat) //...

由于在 main 中为 new-expression 选择了特定于类的重载,因此将丢失其定义。


问题二:

operator new 只返回一个指向原始内存的指针。它不负责在其中构造对象。

对象由 new 表达式 构造,并在必要时调用构造函数。语法遵循变量定义的语法。例如

W = new ("test", 20) Watchdog;

调用 Watchdog 对象的默认构造函数,同时

W = new ("test", 20) Watchdog(arg1, arg2, arg3);

将尝试调用匹配三个参数的构造函数重载。

new-expression 中的第一个参数列表不用作构造函数的参数,而是分配函数需要的参数,以便提供指向对象可以在其中访问的内存的正确指针 build 。


另请注意,operator new 应该为(至少)count(第一个参数)字节分配内存。此参数将提供由 new-expression 构造对象所需的正确值。当您使用 operator newnew 的数组版本时,这一点尤为重要。


另请注意,您仅在 operator new 重载提供的共享内存中构造 Watchdog 对象自身。您的类(class)是否应该使用 new 来分配内存,例如void* m_data 成员,它不会使用您的 operator new 进行分配,而是使用常规分配函数,它将(像往常一样)在进程中分配(非共享)内存空间。

这同样适用于由您的类的非平凡成员分配的内存,例如 std::string m_name。当它需要分配内存时(如果 SSO 不足),它将使用常规分配函数(在非共享内存中)为字符串数据分配内存,而不是您的 operator new 重载。

这意味着,例如,m_name 不能从与您共享内存的其他进程安全地使用。

关于c++ - 从类重载的新运算符运行非默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58582570/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com