我有一个 C++ 框架,我提供给我的用户,他们应该使用我用自己的实现编写的模板化包装器作为模板化类型。包装器充当 RAII 类,它持有一个指向用户类实现的指针。为了使用户的代码干净整洁(在我看来),我提供了一个强制转换运算符,它将我的包装器转换为它所持有的指针。这样(连同其他一些重载)用户可以使用我的包装器,就好像它是一个指针(很像一个 shared_ptr)。
我遇到了一个极端情况,用户调用一个函数,该函数使用指向他的实现类的指针,在我的包装器上使用 std::move。下面是它的外观示例:
#include <iostream>
using namespace std;
struct my_interface {
virtual int bar() = 0;
};
template <typename T>
struct my_base : public my_interface {
int bar() { return 4; }
};
struct my_impl : public my_base<int> {};
template <typename T>
struct my_wrapper {
my_wrapper(T* t) {
m_ptr = t;
}
operator T*() {
return m_ptr;
}
private:
T* m_ptr;
};
void foo(my_interface* a) {
std::cout << a->bar() << std::endl;
}
int main()
{ …Run Code Online (Sandbox Code Playgroud) 假设我有一个元组,t它的类型是std::tuple<T1,T2,T3>每个元组都T可以是Obj, Obj&, Obj&&, const Obj&。我想编写一个函数,将元组的值解包成一个函数f,该函数接受三种衰减到Obj. 我想尽可能避免无用的复制,我该怎么做?
我目前的实现是
static R call(C2&& c, TUP&& x) {
using TUP0 = typename std::remove_reference<TUP>::type;
return c(std::forward<typename std::tuple_element<0, TUP0>::type>(std::get<0>(x)),
std::forward<typename std::tuple_element<1, TUP0>::type>(std::get<1>(x)),
std::forward<typename std::tuple_element<2, TUP0>::type>(std::get<2>(x)));
}
Run Code Online (Sandbox Code Playgroud)
但这种实现看起来move当事情TUP是std::tuple<Obj,Obj,Obj>,即使当TUP包含它应该只动Obj&&。
假设我有以下课程:
#include <vector>
class Foo
{
public:
Foo(const std::vector<int> & a, const std::vector<int> & b)
: a{ a }, b{ b } {}
private:
std::vector<int> a, b;
};
Run Code Online (Sandbox Code Playgroud)
但是现在我想考虑构造函数的调用者可能会将临时变量传递给它的情况,并且我想将这些临时变量正确地移动到a和b。
现在我真的需要再添加 3 个构造函数,其中 1 个a作为右值引用,其中 1 个b作为右值引用,1 个只有右值引用参数吗?
当然,这个问题可以推广到任何数量的值得移动的参数,并且所需构造函数的数量将是参数^2 2^参数。
这个问题也适用于所有函数。
这样做的惯用方法是什么?还是我在这里完全遗漏了一些重要的东西?
来自N3337:
如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时
X没有用户声明的复制构造函数,X没有用户声明的复制赋值运算符,X没有用户声明的移动赋值运算符,X没有用户声明的析构函数,并且移动构造函数将不要隐式定义为已删除.
第一个问题是:为什么编译器在不应该生成移动构造函数时(存在用户声明的析构函数和其他阻止生成移动构造函数的函数).下面的示例程序打印constructorCounter=5表示使用了移动构造函数(没有移动操作值:: constructorCounter应该是10)
#include <iostream>
class value {
public:
value() {
++constructorCounter;
}
value(const int value)
: _value(value)
{
++constructorCounter;
}
value(const value& other)
: _value(other._value)
{
++constructorCounter;
}
const value& operator=(const value& rhs) {
_value = rhs._value;
return _value;
}
~value() { }
static int constructorCounter;
private:
int _value;
};
int value::constructorCounter = 0;
class array {
public:
// array() = delete;
// array(array&&) = delete;
array(const int size)
: _size(size), _values(new value[size])
{
std::clog …Run Code Online (Sandbox Code Playgroud) 下面的代码将数据从一个向量复制到另一个向量。如果向量很大,那么我猜这很昂贵。是否可以在此处使用移动语义将数据从一个向量复制到另一个向量?
std::vector<double> newData(Shape.Size(), 0);
std::vector<double> oldData = a->getData();
std::copy(oldData.begin(), oldData.end(), newData.begin());
Run Code Online (Sandbox Code Playgroud) 我正在执行一些关于移动语义的测试,我的类行为对我来说似乎很奇怪。
鉴于模拟类VecOfInt:
class VecOfInt {
public:
VecOfInt(size_t num) : m_size(num), m_data(new int[m_size]) {}
~VecOfInt() { delete[] m_data; }
VecOfInt(VecOfInt const& other) : m_size(other.m_size), m_data(new int[m_size]) {
std::cout << "copy..." <<std::endl;
std::copy(other.m_data, other.m_data + m_size, m_data);
}
VecOfInt(VecOfInt&& other) : m_size(other.m_size) {
std::cout << "move..." << std::endl;
m_data = other.m_data;
other.m_data = nullptr;
}
VecOfInt& operator=(VecOfInt const& other) {
std::cout << "copy assignment..." << std::endl;
m_size = other.m_size;
delete m_data;
m_data = nullptr;
m_data = new int[m_size];
m_data …Run Code Online (Sandbox Code Playgroud) 我正在使用嵌入式模板化库 etl::queue
https://www.etlcpp.com/queue.html
在etl::queueIS quitvalent到std::queue
为了避免复制,我想将元素实际移动到队列中。
现在我的设置看起来像这样
bool CETLConcurrentQueue<ElementType_T, u32QueueSize>::Add(ElementType_T &&element, const uint32_t u32Timeout)
{
//lock mutex...
queue.push(element);
//do further stuff
}
Run Code Online (Sandbox Code Playgroud)
现在我不使用了,queue.push(std::move(element));因为 element 已经是一个右值引用了
但是,queue.push(element);调用元素复制构造函数(已删除)如何改为调用元素移动构造函数?
int c = 2;
int d = std::move(c);
std::cout << "c is: " << c << std::endl;
std::cout << "d is: " << d << std::endl;
Run Code Online (Sandbox Code Playgroud)
此代码输出:
c是:2
d 是:2
我认为在 move(c) 到 d 之后,c 将是空的,为什么它的值仍然是 2?你能帮我解释一下吗?谢谢你。
TLDR - 如果是这样,请随意将其标记为重复;我会删除问题。然而,我环顾四周后没有找到任何东西。
考虑以下类:
class Base
{
public:
Base(std::string var1);
Base& operator=(Base&& other) noexcept
{
if (this != &other)
var1_ = std::move(other.var1_);
return *this;
}
protected:
std::string var1_;
};
class Child final : public Base
{
public:
Child(std::string var1, std::string var2);
Child& operator=(Child&& other) noexcept
{
if (this != &other)
{
// Take note of HERE for explanation below
Base::operator=(std::move(other));
var2_ = std::move(other.var2_);
}
}
private:
std::string var2_;
};
Run Code Online (Sandbox Code Playgroud)
这里有两个类,Child从Base. Child拥有比 多的成员Base。在 的移动赋值运算符中 …
我有以下代码:
#include <bits/stdc++.h>
using namespace std;
class A {
public:
A(const A& a) noexcept { cout << "copy constructor" << endl; }
A& operator=(const A& a) noexcept { cout << "copy assignment operator" << endl; }
A(A&& a) noexcept { cout << "move constructor" << endl; }
A& operator=(A&& a) noexcept { cout << "move assignment operator" << endl; }
A() { cout << "default constructor" << endl; }
};
vector<A> aList;
void AddData(const A&& a)
{
aList.push_back(std::move(a));
}
int …Run Code Online (Sandbox Code Playgroud)