小编alf*_*lfC的帖子

班级是否应该具有双重破坏的弹性?

我有一种情况,其中同时访问的容器的分配器需要调用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)

c++ destructor

1
推荐指数
1
解决办法
99
查看次数

如何返回转发引用?

返回前向(通用)引用的最自然方式是什么?

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)

c++ return c++11 forwarding-reference

1
推荐指数
1
解决办法
69
查看次数

使用移动元素调整向量大小是否正确?

我试图理解移动语义的通用规则。特别是容器和包含的元素。

原因是我试图在所有权和迭代器失效的背景下理解移动。为此,我将经历一些复杂性不断增加的案例,涉及典型容器、通用包含类型T、通用gf函数。(也许一个重要的额外细节是,f实际上可能会或可能不会执行移动操作,或者它可能在运行时是偶然的。)

这个想法是引入案例3,这是这个问题的核心。

案例0

首先是一个相当没有争议的案例,这是可以的:

std::vector<T> v(100, t);
f(std::move(v));
v = make_a_vector();
Run Code Online (Sandbox Code Playgroud)

情况1

然而,移动后使用可能是臭代码

std::vector<T> v(100, t);
f(std::move(v));
g(v);
Run Code Online (Sandbox Code Playgroud)

我想大多数人都同意上面的做法是不行的。规则是(据我所知)移动后的唯一操作应该是赋值。我认为这尤其是因为它没有记录(未定义但有效的状态)移出向量的状态是什么(或者即使它被移动了)。因此,充其量v是空的,最坏的v情况是未指定的状态,因此g可以在此范围内执行未指定的操作。

案例2:

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?

案例3:

现在是真正棘手的情况。

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)

c++ vector stdvector move-semantics

1
推荐指数
1
解决办法
120
查看次数

解除引用的InputIterator的地址?istream_iterator的情况

我有一个遗留代码,其中为指针定义了接口.我试图调整一些函数来获取迭代器,例如转发迭代器.

是否允许使用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)

c++ istream-iterator dereference

0
推荐指数
1
解决办法
69
查看次数

将 boost::filesystem::path 转换成字符?

我已经研究出如何将 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++ arrays boost input char

0
推荐指数
1
解决办法
3203
查看次数

不理解 std::filesystem::directory_iterator

我刚刚开始研究 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)

c++

0
推荐指数
1
解决办法
1154
查看次数

我在哪里可以找到std :: launder真正做的事情?

我试图理解它是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,或者它只是更多的编译器魔术(挂钩)?

c++ pointer-aliasing reinterpret-cast c++17

-2
推荐指数
1
解决办法
531
查看次数