标签: move-semantics

为什么同时拥有默认析构函数和向量成员会阻止类成为“不可抛出可移动构造函数”?

给出以下代码:

#include <iostream>
#include <vector>
#include <type_traits>

class Test {
public:
    ~Test() = default;
    std::vector<int> m_vector;
};


int main() {
    std::cout << std::is_nothrow_move_constructible_v<Test> << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它输出0,这意味着该类Test不能“不移动”。但是,如果我删除其中一个~Test()m_vector那么它会返回1.

请问这个怎么解释?

作为参考,我将 clang++-7 与 C++17 一起使用。

c++ destructor type-traits move-semantics c++17

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

PhantomPinned 成员会使我的结构具有固定的内存地址吗?

我正在编写与 C API 通信的 Rust 代码,并且我需要某个结构来拥有固定的内存地址。到目前为止,我发现:

如果我理解正确,PhantomPinned这将是最容易使用的:只需将其作为成员即可使我的结构自动具有固定的内存地址。它是否正确?

memory move-semantics rust

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

交换 const 成员是未定义的行为吗?C++17

https://godbolt.org/z/E3ETx8a88

这是换UB吗?我有变异什么吗?UBSAN 没有报告任何内容。

#include <utility>

struct MyInt
{
    MyInt(int ii): i(ii) {}
    const int i;
    MyInt& operator=(MyInt&& rh)
    {
        std::swap(const_cast<int&>(i), const_cast<int&>(rh.i));
        return *this;
    }
};

int main() {
    MyInt i0(0);
    MyInt i2(2);

    i0 = std::move(i2);
    return i0.i;
}
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics c++17

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

从已释放的指针移动会泄漏内存吗?

我有以下代码:

\n
std::unique_ptr<T> first = Get();\n\xe2\x80\xa6\nT* ptr_to_class_member = GetPtr(obj);\n*ptr_to_class_member = std::move(*first.release());\n
Run Code Online (Sandbox Code Playgroud)\n

这是否会按预期运行,没有副本、1 次移动并且没有内存泄漏?

\n

c++ smart-pointers move-semantics

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

我应该预防性地移动可调用对象(例如 lambda 吗?)

我有一个计时器的精简示例,我希望可以使用任何类型的可调用来实例化它。为了提高效率,是否建议预防性地将可调用对象移至数据成员中?

#include <concepts>
#include <cstdio>
#include <string>
#include <utility>

template <std::invocable Cb>
class timer {
public:
    timer(Cb cb)
        : cb_ { std::move(cb) }
    {
    }

    auto call()
    {
        cb_();
    }

private:
    Cb cb_;
};

int main()
{
    std::string something_to_print = "Hello World!\n";
    timer some_timer([&]() { printf(something_to_print.c_str()); });
    some_timer.call();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果移动或复制 lambda,我看不到程序集有任何差异。它有什么区别吗?

c++ lambda move-semantics

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

使用具有 std::expected 返回值的工厂函数时如何避免调用析构函数两次而无需运行时成本

这是关于嵌入式 C++ 的。假设我有一个 struct Timer_t

创建一个新对象

  • 构造函数是私有的
  • 我们有一个作为公共成员的工厂功能makeTimer()

我们不能在设备上使用异常,并且要初始化计时器,我们可能会收到错误。

这就是为什么

  • 默认构造函数对用户隐藏
  • 使用工厂函数
  • 工厂函数返回std::expected<Timer_t,Error_t>

由于我们使用 C++,人们往往会失败(太频繁地叫我来这里)

  • 构造函数的初始化能力很强
  • 析构函数具有强大的去初始化能力

构造函数在这里只能使用一半,工厂函数对我们来说就是这样。

对于析构函数来说它工作得很好。如果我们离开了这个范围,我们就会取消它的初始化。事情应该是这样的。

现在问题开始了:如果我们返回makeTimer()对象,我们就可以移动。

更准确地说,我们称之为move constructor

因此我们有 2 个对象,我们将对象称为析构函数。

更准确地说:

makeTimer() -> Timer_t() -> std::move/Timer_t(Timer_t &&) -> ~Timer_t() ->  program ends -> ~Timer_t(); 
Run Code Online (Sandbox Code Playgroud)

对于移动来说,这是预期的行为。因此,它符合标准,但很烦人。

在嵌入式环境中,我发现人们在扩展代码时会面临很大的失败风险。

我只想在最后调用一次析构函数。

  • 如果我使用 Timer_t 作为返回,它就可以工作!(这就是令人沮丧的地方)
  • 我禁止使用非平凡类型(呃!或者我从未见过这个特定计时器事物的好例子)
  • 使用Error_t makeTimer(Timer_t & uninitialized Type)(会扼杀 std::expected 背后的想法并使代码不那么“好”)
  • 使用标志/计数器std::shared_ptr(额外费用...)或简单的布尔值。

有没有更好的更清洁的想法来解决这个问题?我不可能是唯一一个拥有它的人。

c++ embedded move-semantics std-expected

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

这是滥用/误用Move Semantics吗?

当人们通常讨论或使用移动语义时,通常是在移动两个相同类型的类的上下文中.

例如:

MyObject(MyObject &&obj) { // Implementation }
Run Code Online (Sandbox Code Playgroud)

但是,如果MyObject在很大程度上只是像矢量一样包装STL容器,那该怎么办呢?是否会采用移动构造函数来获取向量并将其视为滥用功能?

MyObject(vector<backingtype> &&v) : i_Backing(move(v)) {}  
Run Code Online (Sandbox Code Playgroud)

我问这个是因为我正在制作一个UTF-8感知的json解析器,它大量使用复制,而移动容器则足够快.

auto arrayParseRes = jsonArrayParse(input); // Array parse res
auto jsonArray = JsonArray(arrayParseRes.Parse_Value()); // Currently copying json values
Run Code Online (Sandbox Code Playgroud)

c++ move-semantics

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

为什么std :: vector需要移动构造函数用于其元素?

C++ 98声明std :: vector元素应该有copy-constructors.在C++ 11中,情况已不再如此.相反,元素必须具有移动构造函数.

根据你对std :: vector的处理方式,你可能真的需要或者可能不需要调用copy-或move-构造函数,但标准中始终只需要其中一个.为什么?

更新:显然,前提是不正确的.我的困惑从阅读的答案,如朵朵.

c++ stl vector move-semantics c++11

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

std :: move的简写

对于某些类来说S,重载一元operator +(或者可能operator *是非指针式类)如下所示是不好的做法?

struct S { S && operator + () & noexcept { return std::move(*this); } };
Run Code Online (Sandbox Code Playgroud)

它的目标是发明速记std::move.

S a;
S b = +a;
// instead of
S c = std::move(a);
Run Code Online (Sandbox Code Playgroud)

假设我有一个包含大量不同类的项目,它集中使用了移动语义.所有类都不模仿任何算术对应物.

c++ operator-overloading rvalue-reference move-semantics perfect-forwarding

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

C++是否具有移动和删除语义?

是否有可能在C++中创建一次性变量而没有任何带有括号的时髦业务?

这是我想要实现的一个例子:

const float _phiTemp  = atan2(tan(cluster.beta), tan(cluster.alpha));
const float phi       = HALF_PI - std::abs(HALF_PI - std::abs(_phiTemp));
// After running this code I want _phiTemp to be unaccessible, and the
// compiler to send an error if I ever try
Run Code Online (Sandbox Code Playgroud)

这是我想要的漫长而丑陋的实现:

const float phi = 0;
{
     const float _phiTemp  = atan2(tan(cluster.beta), tan(cluster.alpha));
     float& phiRef = const_cast<float&> phi;
     phiRef = HALF_PI - std::abs(HALF_PI - std::abs(std::move(_phiTemp)));
}
// _phiTemp is disposed and phi is a const, and safely used in the …
Run Code Online (Sandbox Code Playgroud)

c++ scope lifetime delete-operator move-semantics

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