具有 const 引用的可变参数模板
Variadic templates with const references
我的项目使用按以下方式构造对象的自定义分配器:
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...);
}
有一个 class,包含 const 引用作为字段:
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
每当您想使用 placement-new.
时再次考虑数据对齐
来电
A* a = create<A>(*str);
创建 *str
的副本并使用该副本调用该函数,因为该函数被声明为
template <typename T, typename... Args>
T* create(Args... args) {...}
a
引用了一个不再存在的对象。
使用
template <typename T, typename... Args>
T* create(Args&&... args)
{
T* object = // request "bare" memory
// call object constructor
return new(reinterpret_cast<void*>(object)) T(std::forward<Args>(args)...));
}
相反。
我的项目使用按以下方式构造对象的自定义分配器:
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...);
}
有一个 class,包含 const 引用作为字段:
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
每当您想使用 placement-new.
时再次考虑数据对齐来电
A* a = create<A>(*str);
创建 *str
的副本并使用该副本调用该函数,因为该函数被声明为
template <typename T, typename... Args>
T* create(Args... args) {...}
a
引用了一个不再存在的对象。
使用
template <typename T, typename... Args>
T* create(Args&&... args)
{
T* object = // request "bare" memory
// call object constructor
return new(reinterpret_cast<void*>(object)) T(std::forward<Args>(args)...));
}
相反。