我有一种情况,其中同时访问的容器的分配器需要调用placement new和析构函数.
template< class U > void destroy(U* p){
p->~U();
}
Run Code Online (Sandbox Code Playgroud)
因为它是我最终可以反复呼吁破坏.这让我想到这样的事情是否应该没问题.
std::vector<int>* p = (std::vector<int>*)malloc(sizeof(std::vector<int>));
::new (*p) std::vector<int>(30);
(*p)[10] = 5;
p->~std::vector<int>();
p->~std::vector<int>();
free(p);
Run Code Online (Sandbox Code Playgroud)
我认为只要破坏std::vector
将数据指针设置为null或size为零,并且再次调用时没有双重释放,这将起作用.
那么,是否应该制作课程以使意外(或良性)双重破坏相当于一次破坏?
换句话说,破坏应该是一种幂等的操作吗?
(为简单起见,请注意析构函数在此示例中不是虚拟的)
我发现问题类似于如何允许移动的类稍后被破坏的问题.
一些答案将运行时成本用于支持双重破坏.有成本,但它们与移动物体的成本相似.换句话说,如果移动便宜,允许双重破坏是很便宜的(如果由于其他原因,例如标准,DD首先不是UB).
再具体一点:
class dummyvector{
int* ptr;
public:
dummyvector() : ptr(new int[10]){}
dummyvector(dummyvector const& other) = delete; // for simplicity
dummyvector(dummyvector&& other) : ptr(other.ptr){
other.ptr = nullptr; // this makes the moved object unusable (e.g. set) but still destructable
}
dummyvector& operator=(dummyvector const&) = delete; // for simplicity
void …
Run Code Online (Sandbox Code Playgroud) 返回前向(通用)引用的最自然方式是什么?
struct B{
template<class Ar> friend
/* 1*/ Ar&& operator<<(Ar&& ar, A const& a){...; return std::forward<Archive>(ar);}
template<class Ar> friend
/*OR 2*/ Ar& operator<<(Ar&& ar, A const& a){...; return ar;}
template<class Ar> friend
/*OR 3*/ Ar operator<<(Ar&& ar, A const& a){...; return std::forward<Ar>(ar);}
template<class Ar> friend
/*OR 4*/ Ar operator<<(Ar&& ar, A const& a){...; return ar;}
/*OR 5*/ other??
}
Run Code Online (Sandbox Code Playgroud)
我想到的情况是一个类似流的对象,它被构造并立即使用.例如:
dosomethign( myarchive_type{} << B{} << B{} << other_unrelated_type{} );
Run Code Online (Sandbox Code Playgroud) 我试图理解移动语义的通用规则。特别是容器和包含的元素。
原因是我试图在所有权和迭代器失效的背景下理解移动。为此,我将经历一些复杂性不断增加的案例,涉及典型容器、通用包含类型T
、通用g
和f
函数。(也许一个重要的额外细节是,f
实际上可能会或可能不会执行移动操作,或者它可能在运行时是偶然的。)
这个想法是引入案例3,这是这个问题的核心。
首先是一个相当没有争议的案例,这是可以的:
std::vector<T> v(100, t);
f(std::move(v));
v = make_a_vector();
Run Code Online (Sandbox Code Playgroud)
然而,移动后使用可能是臭代码
std::vector<T> v(100, t);
f(std::move(v));
g(v);
Run Code Online (Sandbox Code Playgroud)
我想大多数人都同意上面的做法是不行的。规则是(据我所知)移动后的唯一操作应该是赋值。我认为这尤其是因为它没有记录(未定义但有效的状态)移出向量的状态是什么(或者即使它被移动了)。因此,充其量v
是空的,最坏的v
情况是未指定的状态,因此g
可以在此范围内执行未指定的操作。
std::vector<T> v(100, t);
f(std::move(v));
v.resize(120);
Run Code Online (Sandbox Code Playgroud)
这是对的吗?这不是一项任务,但resize
没有先决条件。(发现这个Can I resize a vector that was moving from?)
现在是真正棘手的情况。
std::vector<T> v(100);
h(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()));
v.resize(120);
Run Code Online (Sandbox Code Playgroud)
(这里,h
是一个采用迭代器的函数,假设它隐式引用 range 。 [iterator1, iterator2)
)
这是正确的代码吗?原因是.resize
似乎要播放、移动、交换和复制类型为移出的对象T
。
总而言之,调整其元素已(可能)移出的向量的大小是否正确?
编辑:为了论证,让我们指定函数的签名,以防它们与答案相关:
template<class …
Run Code Online (Sandbox Code Playgroud) 我有一个遗留代码,其中为指针定义了接口.我试图调整一些函数来获取迭代器,例如转发迭代器.
是否允许使用InputIterator解除引用的元素的地址,例如istream_iterator
?
结果是暂时的,并且必须在内存的某个地方进行通话,但我不确定.
以下示例使用double
,但类型可能更复杂(大).
#include<iostream>
#include<iterator>
#include<sstream>
void f_legacy(double const* t){
std::cout << *t << std::endl;
};
void f(std::istream_iterator<double> it){
f_legacy(std::addressof(*it)); // OK????
// to avoid a copy: auto v = *it; f_legacy(std::addressof(v));
}
int main(){
double d = 5.;
std::istringstream iss("1 2 3");
std::istream_iterator<double> it(iss);
f_legacy(&d);
f(it);
}
Run Code Online (Sandbox Code Playgroud) 我已经研究出如何将 boost 路径传递为所需的格式,但是我遇到了一些问题,无法将 path.stem 传递到 char 数组中,然后对文件名进行一些检查并采取正确的操作
需要读取文件名并检查然后操作中的下一个可用数字,我打算使用 for 循环将数字放入一个字符数组中,然后与这个单独的计数器进行比较
我如何将 path() 逐字符输入到数组中 - 或者有更好的方法!
int count(boost::filesystem::path input) {
cout << "inputzz : " << input << endl;
char data;
wstring winput;
for (int a = 0; a < 4;){
//boost::filesystem::absolute(input).string();
//cout << input.generic_string() << endl;
(input.generic_string()) >> data;
data << (boost::filesystem::path()input.generic_string());
//a++
};
Run Code Online (Sandbox Code Playgroud) 我刚刚开始研究 C++,并且一直在读一本书,但只读了其中的几章。
我认为打印一个目录是一个很好的练习。当我查找时,我看到这个漂亮的环路正在驾驶for
火车。
for (const auto & entry : fs::directory_iterator(path))
std::cout << entry.path() << std::endl;
Run Code Online (Sandbox Code Playgroud)
我的下一个逻辑步骤是将这些值存储在向量或数组中。
在过去的三个小时里,我一直无法弄清楚。什么是entry
?它是一个常数吗?是字符串吗?是什么阻止我将它放入向量中?我无法让这段代码运行。
我对这个基本问题感到抱歉,我只需要一些概念上的澄清。
这是我的代码,push_back()
不接受常量,并且无法将常量转换为字符串。我缺少什么?
auto filepath()
{
std::vector <string> lis;
std::string path = "C:/Users/Derek Comeau/3D Objects";
for (const auto& entry : filesystem::directory_iterator(path)) {
const string paths = entry.path();
lis.push_back(paths);
}
}
Run Code Online (Sandbox Code Playgroud) 我试图理解它是std::launder
做什么的,我希望通过查找一个示例实现,它将是清楚的.
我在哪里可以找到一个示例实现std::launder
?
当我查看lbic ++时,我看到了类似的代码
template<typename _Tp>
[[nodiscard]] constexpr _Tp*
launder(_Tp* __p) noexcept
{ return __builtin_launder(__p); }
Run Code Online (Sandbox Code Playgroud)
这让我觉得这是另一个编译魔术函数.
这个函数__builtin_launder
可能会做什么,它是否只是添加一个标记来抑制编译器有关别名的警告?
是否可以理解std::launder
来讲__builtin_launder
,或者它只是更多的编译器魔术(挂钩)?