我想创建一个移动构造函数,它接受字符串文字,然后将该c字符串移动到成员指针。 我能写的最佳解决方案是发出警告: 已弃用从字符串常量转换为' char *' [-Wwrite串] CTextBlock cctb(" move(H)"); ^ 代码:
#include <iostream>
using namespace std;
class CTextBlock
{
public:
CTextBlock(char* &&text)//move constructor
{
pText = text;
}
private:
char *pText;
};
int main()
{
CTextBlock cctb("move(H)"); //WARNING
return 0;
}
答案 0 :(得分:3)
首先,字符串文字的类型是char const[N]
(对于合适的常量N
)。可以将此数组分配给char const*
,在这种情况下,它将衰减为指向第一个元素的指针。 无法转换为char*
。在C ++ 11之前,允许转换为char*
来处理不是const
的现有代码 - 正确(例如,因为它在C得到const
之前作为C代码开始) 。 C ++ 11已删除此转换。
问题是你实际尝试实现的目标:字符串文字是不可变的,并且在程序的整个生命周期中都是持久的。你可以随意保留尽可能多的指针,移动指针是没有意义的,因为复制起来很便宜。
在你的问题中,你表明你想创建一个移动构造函数,但是移动构造函数会获取它们所用类的右值引用,例如,这将是你类的移动构造函数:
CTextBlock::CTextBlock(CTextBlock&& other)
: pText(other.pText) {
other.pText = 0;
}
(你的类没有显示指针pText
的任何所有权语义,在这种情况下,移动构造实际上没有多大意义;上面的代码假定存在一些所有权语义并且空指针指示该对象没有任何东西)。
仅仅因为参数被约束为rvalue引用并不意味着该函数是一个移动构造函数。它所暗示的是,参数是一个rvalue,它可以合理地假设它的当前表示不需要保留。字符串文字似乎是一个右值,因为字符串文字被转换为指向数组开头的[临时]指针。
答案 1 :(得分:0)
合理接近只允许文字的构造函数可以实现为模板:
#include <cstddef>
#include <assert>
struct X
{
char const * str;
std::size_t len;
template <std::size_t N>
X(char const (&a)[N]) : str(a), len(N - 1)
{
assert(a[len] == '\0'); // true for string literals
}
};
但是,这并不是万无一失的,因为它也会绑定到命名的字符数组,如果你的字符串也包含空值,则长度计算是不确定的。但是如果你试图避免意外使用动态值(例如在从表达式和文字字符串构建字符串的算法中),这是非常有用的。
答案 2 :(得分:-2)
字符串文字是const char *
。无论是否将其用作左值或右值,都是如此。
如果您再次查看代码,则会尝试将const char *
存储到char *
,以及编译器诊断所来自的位置。您的移动构造函数正在对char *
进行右值引用,而不是const char *
。将其更改为const char *
,并将pText
班级成员更改为const char *
,您尝试执行的操作应该有效。