我想知道为什么std::move带有右值参数的函数实际上没有移动任何东西,而是通过引用传递?
特别是当我知道它适用于构造函数时。
我正在运行以下代码:
#include <memory>
#include <iostream>
void consume_ptr(std::shared_ptr<int> && ptr) {
std::cout << "Consumed " << (void*) ptr.get() << std::endl;
}
int main(int argc, char ** argv)
{
std::shared_ptr<int> ptr = std::make_shared<int>();
consume_ptr(std::move(ptr));
if (ptr) {
std::cout << "ptr should be moved?" << std::endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
ptr should be moved?
Run Code Online (Sandbox Code Playgroud)
根据我读到的所有内容,std::shared_ptr应该已移动到函数内部,这意味着对象本身在将其移动到 后将ptr保持不变,但事实并非如此!nullptrconsume_ptr
我用我的一些带有日志记录的自定义类尝试了它,看起来移动构造函数甚至从未被调用。它在每个编译器和优化级别下都可以重现。
有人可以帮我解决这个问题吗?
我遇到了类似于以下(或多或少最小)示例的 C++ 代码。请考虑底部函数中标记的方法调用:
#include <memory>
static unsigned returnValue = 5;
void setReturnValue(unsigned u) { returnValue = u; }
class MyObject
{
public:
MyObject(unsigned uIN) : u(uIN) {}
~MyObject() { u = 42; }
void method(std::unique_ptr<MyObject> uniqPtrToObject)
{
// Do something fancy with this unique pointer now,
// which will consume the object and its data
setReturnValue(uniqPtrToObject->getValue());
}
unsigned getValue() { return u; }
private:
unsigned u; // Some relevant object data
};
std::unique_ptr<MyObject> GetUniqToObject(unsigned u)
{
// Get the object …Run Code Online (Sandbox Code Playgroud) 比较以下两种情况:
template<class... Args>
void f1(Args&&... args) { do_smth(std::forward<Args>(args)...); }
auto f2 = [](auto&&... args) { do_smth(std::forward<decltype(args)>(args)...); };
Run Code Online (Sandbox Code Playgroud)
std::forward传递或不传递的类型是否有任何差异?
根据我的理解,当您使用 , 指定转发引用时T&&,&&并不与传递的参数“匹配”,而是一种将“原始引用”信息“存储”到T(T将是&, const &,&&或const &&根据值类别传递的参数),然后将此类“原始引用”信息结合起来,使用通常的规则等&&计算最终的引用类型。& + && = &
我不知道的是,是否decltype(args)会解析为此类计算“之前”或“之后”的类型,或者结果类型是否与“原始引用”不同,因此指定的类型是否有任何差异std::forward在f1和f2.
注意:我不能使用 C++20,并且模板 lambda 不在问题范围内。
我用TDM-GCC 4.6.1编译器对rvalue引用做了一些实验,并做了一些我无法用理论解释的有趣观察.我想那里的专家帮我解释一下.
我有一个非常简单的程序,不处理对象,但int原语,并定义了2个函数:foo1(通过rvalue引用返回局部变量)和foo2(按值返回局部变量)
#include <iostream>
using namespace std;
int &&foo1();
int foo2();
int main()
{
int&& variable1 = foo1();
//cout << "My name is softwarelover." << endl;
cout << "variable1 is: " << variable1 << endl; // Prints 5.
cout << "variable1 is: " << variable1 << endl; // Prints 0.
int&& variable2 = foo2();
cout << "variable2 is: " << variable2 << endl; // Prints 5.
cout << "variable2 is still: " << variable2 << endl; // Still prints …Run Code Online (Sandbox Code Playgroud) 将rvalue引用引入C++的典型原因是在评估复杂的C++表达式时消除(优化)多余的复制.
但是,C++ 98/C++ 03 有两种编译器优化技术,它们基本上用于相同的目的,即
有没有任何真实的用例,当上述技术(使用适当编写的代码)无法消除多余的复制,但右值引用可以成功吗?
在某些O类中,我有模板化的函数test2:
struct A{int value;};
struct O{
A value;
template<typename Args>
static void test2(Args &&args){
std::cout << std::endl << "!!!" << std::is_rvalue_reference<decltype(args)>::value << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
比,我想从另一个调用此函数:
template<typename Args>
void test(Args &&args){
using t = decltype(std::forward<Args>(args).value);
std::cout << std::is_rvalue_reference<decltype(args)>::value;
std::cout << std::is_rvalue_reference<decltype(std::forward<Args>(args).value)>::value;
std::cout << std::is_rvalue_reference<t>::value;
// All ok
O.test2(std::forward<Args>(args).value);
// Alvays rvalue, even if agrs is lvalue
O::template test2<t>(
std::forward<t>(
std::forward<Args>(args).value
)
);
// Nor work at all, cant cast A to A&&
O::template test2<t>(
std::forward<Args>(args).value
);
);
} …Run Code Online (Sandbox Code Playgroud) 虽然在我的一些类中实现方法和运算符重载以利用C++中的右值引用,但我经常编写一些设计不良而违反DRY原则的代码.对于下面的代码片段,什么是更好的替代方案?(这段代码只是为了说明问题)
class matrix_2_2
{
int _m[2][2];
public:
matrix_2_2 operator*(const matrix_2_2& m) const &
{
matrix_2_2 res;
for(int i = 0 ; i < 2 ; i ++)
for(int j = 0 ; j < 2 ; j++)
for(int k = 0 ; k < 2 ; k++)
res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);
return res;
}
matrix_2_2 operator*(matrix_2_2&& m) &&
{
matrix_2_2 res;
for(int i = 0 ; i < 2 ; i ++)
for(int j = 0 ; j < …Run Code Online (Sandbox Code Playgroud) 假设我有一个元组和一个函数:
typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple;
void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> );
Run Code Online (Sandbox Code Playgroud)
所以在辅助函数中我将元组展开为参数:
void unroll( SomeTuple &t )
{
someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
Run Code Online (Sandbox Code Playgroud)
它有效,但我想避免重复std::move多次.天真的解决方案如:
void unroll( SomeTuple &t )
{
auto &&rt = std::move( t );
someFunction( std::get<0>( rt ), std::get<1>( rt ) );
}
Run Code Online (Sandbox Code Playgroud)
显然不起作用,因为rt是一个lvalue.那么有没有办法避免std::move()每次重复多次std::get?
请考虑以下代码:
#include <string>
#include <map>
#include <memory>
#include <utility>
#include <iostream>
typedef std::shared_ptr<const std::string> ConstDataTypePtr;
typedef std::map<std::string, ConstDataTypePtr> StrDataTypeMap;
int main()
{
StrDataTypeMap m_nameToType;
ConstDataTypePtr vp_int8(new std::string("RGH"));
m_nameToType.insert(std::make_pair<std::string, ConstDataTypePtr>("int8_t", vp_int8));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你必须用:编译它g++ -std=c++11 <filename>.cpp.
它给出以下错误:
testO.cpp: In function ‘int main()’:
testO.cpp:14:88: error: no matching function for call to ‘make_pair(const char [7], ConstDataTypePtr&)’
m_nameToType.insert(std::make_pair<std::string, ConstDataTypePtr>("int8_t", vp_int8));
^
testO.cpp:14:88: note: candidate is:
In file included from /usr/include/c++/4.8.2/bits/stl_algobase.h:64:0,
from /usr/include/c++/4.8.2/bits/char_traits.h:39,
from /usr/include/c++/4.8.2/string:40,
from testO.cpp:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template<class _T1, class …Run Code Online (Sandbox Code Playgroud) 是否允许:
int x = 1;
int r1 = static_cast<int&>(x);
int r2 = static_cast<int&&>(x)
Run Code Online (Sandbox Code Playgroud)
如果是,那么这些演员表的含义是什么?
这个代码引起了问题:
int x = 1;
int y = 2;
std::swap(x, y); // uses int temp = std::move(x);
Run Code Online (Sandbox Code Playgroud) c++ ×10
rvalue-reference ×10
c++11 ×7
c++14 ×1
c++17 ×1
reference ×1
static-cast ×1
stdtuple ×1
templates ×1
unique-ptr ×1