c++ - 具有 const 引用的可变参数模板

标签 c++ c++11 memory-management pass-by-reference variadic-templates

我的项目使用自定义分配器以下列方式构造对象:

template <typename T, typename... Args>
T* create(Args... args)
{
    T* object = // request "bare" memory
    // call object constructor
    return new(reinterpret_cast<void*>(object)) T(args...);
}

有一个类,包含常量引用作为字段:

struct A {
  A(const string& s) : str_(s) {
    cout << &s << '\n';
  }

  const string& str_;
};

但是当我试图创建一个对象时,我得到了错误的结果:

string* str = new string("some string");
cout << str << '\n';
A* a = create<A>(*str);

输出:

0x7fffc8004db4
0x7fffd5436050

我认为 const 引用字段 (str_) 应该包含相同的地址,已提供给建筑机械,但显然这不是真的。

为什么会发生,如何避免?

Ofc,我不能不使用自定义分配器,这是强制性的,我不会问。

最佳答案

template <typename T, typename... Args>
T* create(Args... args)
{
    T* object = // request "bare" memory
    // call object constructor
    return new(reinterpret_cast<void*>(object)) T(args...);
}

所有可变参数都将按值传递。因此正在制作拷贝。您可能想使用转发引用:

template <typename T, typename... Args>
T* create(Args&&... args)
{
    auto memory =  // request "bare" memory
    // call object constructor
    return new(memory) T(std::forward<Args>(args)...);
}

打印:

0x111ac20
0x111ac20

Demo


每当您想使用 placement-new 时,再次考虑数据对齐。

关于c++ - 具有 const 引用的可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43189185/

相关文章:

c++ - 无法将辅助表单显示为MainForm

c++ - 在非唯一集合上使用 erase-remove 习语

c++ - CRTP 编译检测与模板组合

c++ - 为什么 2 + 1 & 0 结果是 0?

c++ - 如果用户定义的构造函数省略了数据成员的初始化,会发生什么?

C++11 for 循环语法不能正常工作

mysql - MySQL中将字符串存储为varchar的内存占用

objective-c - 方法返回的对象的内存管理 (iOS/Objective-C)

iphone - 如何释放 UINavigationController?

快速排序算法抛出堆栈转储错误的 C++ 运行时错误