2011-03-18 63 views
1

如何将变量区分为编译器构造的字符串?C++ 11 - 区分右值指针

例如,而右值"Hello, World"的类型为const char*const char*本身并不意味着指针不能被改变。一个char* const指针不能改变,但这不是编译器构造的。

这是否意味着,对于任何包含const char*的容器,数据应该通过C++的移动语义以外的方式复制?有没有什么办法可以移动编译器构造的字符串,并让所有其他字符串独立?

例如,在GCC 4.5.2中,返回类型int而不是int&的方法被视为返回int&&。我不知道实际的标准是否应该是这样,但这就是GCC目前所做的。

编辑:为了澄清,我的意思是应该复制指针指向的实际内存。这意味着必须分配新的内存,并且指针中的数据应该被复制到新的位置。

+0

我不太了解“编辑”。你能澄清吗? – 2011-03-18 00:55:53

回答

8

"Hello, World"不是类型const char*。它是const char[13]的类型,它是一个左值,而不是右值。

当在其被隐式转换为const char*指向到其初始元素的上下文使用"Hello, World",所得到的指针是一个rvalue(因为它是从隐式转换得到的临时对象。

例如,在GCC 4.5.2,返回类型int而非int&被视为返回int&&的方法。

如果调用由值返回的函数(例如。,int),那么该函数调用表达式是一个右值表达式。如果您调用返回左值引用的函数(例如,int&),那么该函数调用表达式是一个左值表达式。

如何区分一个变量作为编译器构造的字符串?

你不能,真的:"Hello, World"和你可能声明的任何其他const char[13]没有区别。

至于在标准库容器如std::vector中存储const char*或任何其他指针类型,容器不会触及指向的数据:容器正在创建,移动,复制和销毁指针。

如果您需要管理指向数据,您需要通过编写一个类来管理指向的对象(非常类似智能指针类)。编写一个类来管理这种资源的习惯用语称为“资源获取初始化”(RAII)或“范围绑定资源管理”(SBRM)。

+0

感谢您的帮助! – 2011-03-18 00:54:04

+1

Stramge:gcc 4.5为'f(“abcd”)'和'f(ac)'打印“rvalue const char *”。 – GManNickG 2011-03-18 01:18:50

+0

@GMan:这很有趣:它获得了“f(a)”的权利,尽管这很奇怪。 Visual C++ 2010 SP1为'f(new char)'输出“'lvalue char *',这显然是错误的。它还为所有三个左值数组调用打印'lvalue char const *',并拒绝编译两个右值数组调用,结果显示来自Clang 3.0(Trunk 127530),根据最新的C++ 0x草案,我认为它们是正确的;但我会深入研究它的,尽管如此 – 2011-03-18 01:22:28

0

这是否意味着,对于任何包含const char *的容器,数据应该通过除C++的移动语义之外的方式复制?

这意味着指针被复制。没有更多,没有更多。指针必须复制才能使容器正常工作。